/*!common/components/lgAjax/lgAjax.js*/
;(function ($) {
    $.lgAjax = function(opts) {
        var requestConf = {};
        var successCallback =false;
        if(!opts.needNoToken){
            opts.headers ={
                "X-Anit-Forge-Token" : window.X_Anti_Forge_Token || 'None', // 全局Token校验
                "X-Anit-Forge-Code" : window.X_Anti_Forge_Code || '0' // 全局Code校验
            };
        };
        //如果ajax请求用success和error来回调的话做特殊处理，放在done和fail中执行
        if(opts.success){
            successCallback=true;
            for(var i in opts){
                switch(i) {
                    case "success":
                    case "error":
                    break;
                    default:
                    requestConf[i]= opts[i];
                    break;
                };
            };
        }else{
            requestConf = $.extend({},opts);
        }
        var ajax = $.ajax(requestConf)
        .done(function(result,textStatus,xhr){
            //防止重复提交的代码,https://gate.lagou.com 需要把 needNoToken:true,因为这个接口有别的防止重复提交的方法
            if (!opts.needNoToken) {
                try { // 容错，不同场景下success状态不可预知
                    if (result && result.submitToken && result.submitCode) {
                        window.X_Anti_Forge_Token = result.submitToken; // 自动更新X_Anti_Forge_Token
                        window.X_Anti_Forge_Code = result.submitCode; // 自动更新X_Anti_Forge_Code
                    }
                } catch (e) {}
            }
            //做反爬处理
            var location = window.encodeURIComponent(window.location.href);
            var host = window.location.host;
            if(result && result.state){
                switch(result.state){
                    case 2402:
                        window.location.href = 'https://' + host + '/utrack/trackMid.html?f=' + location;
                        break;
                    case 2403://未登录用户同一类页面一分钟内访问超过 10 次则强制跳转至登录页面
                        window.location.href = 'https://passport.lagou.com/login/login.html';
                        break;
                    case 2404:
                        window.location.href = 'https://' + host + '/utrack/verify.html?t=1&f=' + location;
                        break;
                    case 2405://跳转第一级验证
                        window.location.href = 'https://sec.lagou.com/verify.html?e=' + result.errorcode + '&f=' + location;
                        break;
                    case 2406://跳转第二级验证
                        window.location.href = 'https://sec.lagou.com/sms/verify.html?e=' + result.errorcode + '&f=' + location;
                        break;
                    case 2407://跳转直接封禁页面
                        window.location.href = 'https://forbidden.lagou.com/forbidden/fbi.html';
                        break;
                    case 2408://跳转单个请求拦截页面
                        window.location.href = 'https://forbidden.lagou.com/forbidden/fbh.html';
                        break;
                    case 2409:
                        window.location.href = 'https://forbidden.lagou.com/forbidden/fbl.html';
                        break;
                    default: 
                        break;
                }
            };
            if(successCallback){
                opts.success && opts.success(result,textStatus,xhr);
            }
        })
        .fail(function(result,textStatus,xhr){
            if(successCallback){
                opts.error && opts.error(result,textStatus,xhr);
            }
        });
        return ajax;
    }
} )(jQuery);
/*!common/components/util/htoc.js*/
;define('common/components/util/htoc', ['require', 'exports', 'module'], function(require, exports, module) {

  module.exports = {
      // 全角转半角
      HtoC: function(domObj) {
          var str = domObj.val();
          var t = '';
          for (var i = 0; i < str.length; i++) {
              if (str.charCodeAt(i) > 65248 && str.charCodeAt(i) < 65375) {
                  t += String.fromCharCode(str.charCodeAt(i) - 65248);
              } else {
                  t += String.fromCharCode(str.charCodeAt(i));
              }
          }
          domObj.val(t);
      }
  }
  

});
/*!common/static/js/gt.sense.js*/
;define('common/static/js/gt.sense', ['require', 'exports', 'module'], function(require, exports, module) {


    !function(global,factory){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=global.document?factory(global,!0):function(w){if(!w.document)throw new Error("Geetest requires a window with a document");return factory(w)}:factory(global)}("undefined"!=typeof window?window:this,function(window,noGlobal){"use strict";function _Object(obj){this._obj=obj}function Config(config){var self=this;new _Object(config)._each(function(key,value){self[key]=value})}if(void 0===window)throw new Error("Geetest requires browser environment");var document=window.document,Math=window.Math,head=document.getElementsByTagName("head")[0];_Object.prototype={_each:function(process){var _obj=this._obj;for(var k in _obj)_obj.hasOwnProperty(k)&&process(k,_obj[k]);return this}},Config.prototype={api_server:"api.geetest.com",type_path:"/gettype_deepknow.php",protocol:"http://",static_servers:["static.geetest.com","dn-staticdown.qbox.me"],path:"/static/js/sense.js",type:"sense",_extend:function(obj){var self=this;new _Object(obj)._each(function(key,value){self[key]=value})}};var isNumber=function(value){return"number"==typeof value},isString=function(value){return"string"==typeof value},isBoolean=function(value){return"boolean"==typeof value},isFunction=function(value){return"function"==typeof value},random=function(){return parseInt(1e4*Math.random())+(new Date).valueOf()},loadScript=function(url,cb){var script=document.createElement("script");script.charset="UTF-8",script.async=!0,script.onerror=function(){cb(!0)};var loaded=!1;script.onload=script.onreadystatechange=function(){loaded||script.readyState&&"loaded"!==script.readyState&&"complete"!==script.readyState||(loaded=!0,setTimeout(function(){cb(!1)},0))},script.src=url,head.appendChild(script)},normalizeDomain=function(domain){return domain.replace(/^https?:\/\/|\/$/g,"")},normalizePath=function(path){return path=path.replace(/\/+/g,"/"),0!==path.indexOf("/")&&(path="/"+path),path},normalizeQuery=function(query){if(!query)return"";var q="?";return new _Object(query)._each(function(key,value){(isString(value)||isNumber(value)||isBoolean(value))&&(q=q+encodeURIComponent(key)+"="+encodeURIComponent(value)+"&")}),"?"===q&&(q=""),q.replace(/&$/,"")},makeURL=function(protocol,domain,path,query){domain=normalizeDomain(domain);var url=normalizePath(path)+normalizeQuery(query);return domain&&(url=protocol+domain+url),url},load=function(protocol,domains,path,query,cb){var tryRequest=function(at){var url=makeURL(protocol,domains[at],path,query);loadScript(url,function(err){err?at>=domains.length-1?cb(!0):tryRequest(at+1):cb(!1)})};tryRequest(0)},jsonp=function(domains,path,config,callback){var cb="geetest_"+random();window[cb]=function(data){callback("success"===data.status?data.data:data),window[cb]=undefined;try{delete window[cb]}catch(e){}},load(config.protocol,domains,path,{gt:config.id,callback:cb},function(err){err&&throwError("networkError",config)})},throwError=function(errorType,config){var errors={networkError:"网络错误",idNotExist:"参数id必填",cbIlegal:"callback必须是function",geetestNotExist:"Geetest不存在"};if("function"!=typeof config.onError)throw new Error(errors[errorType]);config.onError(errors[errorType])},detect=function(){return!!window.Geetest},initSense=function(userConfig,callback){var config=new Config(userConfig);return userConfig.https?config.protocol="https://":"http:"!==window.location.protocol&&"https:"!==window.location.protocol?config.protocol="https://":config.protocol=window.location.protocol+"//",userConfig&&userConfig.id?callback&&!isFunction(callback)?void throwError("cbIlegal",config):detect()?void(callback&&callback(new window.Geetest(config))):void jsonp([config.api_server],config.type_path,config,function(newConfig){load(config.protocol,newConfig.static_servers,newConfig.path,null,function(err){if(err)throwError("networkError",config);else{if("undefined"==typeof window.Geetest)return void throwError("geetestNotExist",config);config._extend(newConfig),callback&&callback(new window.Geetest(config))}})}):void throwError("idNotExist",config)};return window.initSense=initSense,initSense});    

});


/*!common/widgets/passport/common/js/sense.js*/
;define('common/widgets/passport/common/js/sense', ['require', 'exports', 'module', "common/static/js/gt.sense"], function (require, exports, module) {

    require("common/static/js/gt.sense");

    var sense;

    var isSenseStyleCbList = [];
    var notSenseStyleCbList = [];

    var isNoLagou;

    function getVerifyStyle(cb) {
        $.lgAjax({
            type: "GET",
            url: GLOBAL_DOMAIN.pctx + "/verify/getStyle.json",
            dataType: "jsonp",
            jsonp: "jsoncallback"
        }).done(function (result) {
            cb(result.content.data.verifyStyle);
        });
        // cb("lagou");
    }

    getVerifyStyle(function (result) {
        verifyStyle = result;
        if (verifyStyle == "nolagou") {
            isNoLagou = true;
            initSense({
                id: "66442f2f720bfc86799932d8ad2eb6c7",
                https: true,
                onError: function (err) {
                    console.log("gt error", err);
                }
            }, function (_sense) {
                sense = _sense;
                sense._c_interactive = 0;
                sense.setInfos(function () {
                    return {
                        interactive: sense._c_interactive
                    };
                }).onSuccess(function (data) {
                    sense._c_onSuccess && sense._c_onSuccess(data)
                }).onClose(function () {
                    sense.reset();
                    sense._c_onClose && sense._c_onClose()
                }).onError(function (err) {
                    window.location.reload();
                });
                isSenseStyleCbList.forEach(function(cb) {
                    cb && cb(sense)
                });
            });
            
            return;
        }
        if (verifyStyle == "lagou") {
            isNoLagou = false;
            notSenseStyleCbList.forEach(function(cb) {
                cb && cb(sense)
            });
        }
    });

    module.exports = function(isSenseStyleCb, notSenseStyleCb) {
        if (typeof isNoLagou === "undefined") {
            isSenseStyleCbList.push(isSenseStyleCb);
            notSenseStyleCbList.push(notSenseStyleCb);
            return;
        }

        if (isNoLagou && sense) {
            isSenseStyleCb(sense);
            return;
        }

        if (isNoLagou && !sense) {
            isSenseStyleCbList.push(isSenseStyleCb);
            return;
        }

        notSenseStyleCb();
        
    }
});
/*!common/widgets/passport/dep/socketio-java/socket.other.js*/
;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('common/widgets/passport/dep/socketio-java/socket.other', [],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.io = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){

/**
 * Module dependencies.
 */

var url = _dereq_('./url');
var parser = _dereq_('socket.io-parser');
var Manager = _dereq_('./manager');
var debug = _dereq_('debug')('socket.io-client');

/**
 * Module exports.
 */

module.exports = exports = lookup;

/**
 * Managers cache.
 */

var cache = exports.managers = {};

/**
 * Looks up an existing `Manager` for multiplexing.
 * If the user summons:
 *
 *   `io('http://localhost/a');`
 *   `io('http://localhost/b');`
 *
 * We reuse the existing instance based on same scheme/port/host,
 * and we initialize sockets for each namespace.
 *
 * @api public
 */

function lookup(uri, opts) {
  if (typeof uri == 'object') {
    opts = uri;
    uri = undefined;
  }

  opts = opts || {};

  var parsed = url(uri);
  var source = parsed.source;
  var id = parsed.id;
  var path = parsed.path;
  var sameNamespace = cache[id] && path in cache[id].nsps;
  var newConnection = opts.forceNew || opts['force new connection'] ||
                      false === opts.multiplex || sameNamespace;

  var io;

  if (newConnection) {
    debug('ignoring socket cache for %s', source);
    io = Manager(source, opts);
  } else {
    if (!cache[id]) {
      debug('new io instance for %s', source);
      cache[id] = Manager(source, opts);
    }
    io = cache[id];
  }

  return io.socket(parsed.path);
}

/**
 * Protocol version.
 *
 * @api public
 */

exports.protocol = parser.protocol;

/**
 * `connect`.
 *
 * @param {String} uri
 * @api public
 */

exports.connect = lookup;

/**
 * Expose constructors for standalone build.
 *
 * @api public
 */

exports.Manager = _dereq_('./manager');
exports.Socket = _dereq_('./socket');

},{"./manager":2,"./socket":4,"./url":5,"debug":14,"socket.io-parser":41}],2:[function(_dereq_,module,exports){

/**
 * Module dependencies.
 */

var eio = _dereq_('engine.io-client');
var Socket = _dereq_('./socket');
var Emitter = _dereq_('component-emitter');
var parser = _dereq_('socket.io-parser');
var on = _dereq_('./on');
var bind = _dereq_('component-bind');
var debug = _dereq_('debug')('socket.io-client:manager');
var indexOf = _dereq_('indexof');
var Backoff = _dereq_('backo2');

/**
 * IE6+ hasOwnProperty
 */

var has = Object.prototype.hasOwnProperty;

/**
 * Module exports
 */

module.exports = Manager;

/**
 * `Manager` constructor.
 *
 * @param {String} engine instance or engine uri/opts
 * @param {Object} options
 * @api public
 */

function Manager(uri, opts){
  if (!(this instanceof Manager)) return new Manager(uri, opts);
  if (uri && ('object' == typeof uri)) {
    opts = uri;
    uri = undefined;
  }
  opts = opts || {};

  opts.path = opts.path || '/socket.io';
  this.nsps = {};
  this.subs = [];
  this.opts = opts;
  this.reconnection(opts.reconnection !== false);
  this.reconnectionAttempts(opts.reconnectionAttempts || Infinity);
  this.reconnectionDelay(opts.reconnectionDelay || 1000);
  this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000);
  this.randomizationFactor(opts.randomizationFactor || 0.5);
  this.backoff = new Backoff({
    min: this.reconnectionDelay(),
    max: this.reconnectionDelayMax(),
    jitter: this.randomizationFactor()
  });
  this.timeout(null == opts.timeout ? 20000 : opts.timeout);
  this.readyState = 'closed';
  this.uri = uri;
  this.connecting = [];
  this.lastPing = null;
  this.encoding = false;
  this.packetBuffer = [];
  this.encoder = new parser.Encoder();
  this.decoder = new parser.Decoder();
  this.autoConnect = opts.autoConnect !== false;
  if (this.autoConnect) this.open();
}

/**
 * Propagate given event to sockets and emit on `this`
 *
 * @api private
 */

Manager.prototype.emitAll = function() {
  this.emit.apply(this, arguments);
  for (var nsp in this.nsps) {
    if (has.call(this.nsps, nsp)) {
      this.nsps[nsp].emit.apply(this.nsps[nsp], arguments);
    }
  }
};

/**
 * Update `socket.id` of all sockets
 *
 * @api private
 */

Manager.prototype.updateSocketIds = function(){
  for (var nsp in this.nsps) {
    if (has.call(this.nsps, nsp)) {
      this.nsps[nsp].id = this.engine.id;
    }
  }
};

/**
 * Mix in `Emitter`.
 */

Emitter(Manager.prototype);

/**
 * Sets the `reconnection` config.
 *
 * @param {Boolean} true/false if it should automatically reconnect
 * @return {Manager} self or value
 * @api public
 */

Manager.prototype.reconnection = function(v){
  if (!arguments.length) return this._reconnection;
  this._reconnection = !!v;
  return this;
};

/**
 * Sets the reconnection attempts config.
 *
 * @param {Number} max reconnection attempts before giving up
 * @return {Manager} self or value
 * @api public
 */

Manager.prototype.reconnectionAttempts = function(v){
  if (!arguments.length) return this._reconnectionAttempts;
  this._reconnectionAttempts = v;
  return this;
};

/**
 * Sets the delay between reconnections.
 *
 * @param {Number} delay
 * @return {Manager} self or value
 * @api public
 */

Manager.prototype.reconnectionDelay = function(v){
  if (!arguments.length) return this._reconnectionDelay;
  this._reconnectionDelay = v;
  this.backoff && this.backoff.setMin(v);
  return this;
};

Manager.prototype.randomizationFactor = function(v){
  if (!arguments.length) return this._randomizationFactor;
  this._randomizationFactor = v;
  this.backoff && this.backoff.setJitter(v);
  return this;
};

/**
 * Sets the maximum delay between reconnections.
 *
 * @param {Number} delay
 * @return {Manager} self or value
 * @api public
 */

Manager.prototype.reconnectionDelayMax = function(v){
  if (!arguments.length) return this._reconnectionDelayMax;
  this._reconnectionDelayMax = v;
  this.backoff && this.backoff.setMax(v);
  return this;
};

/**
 * Sets the connection timeout. `false` to disable
 *
 * @return {Manager} self or value
 * @api public
 */

Manager.prototype.timeout = function(v){
  if (!arguments.length) return this._timeout;
  this._timeout = v;
  return this;
};

/**
 * Starts trying to reconnect if reconnection is enabled and we have not
 * started reconnecting yet
 *
 * @api private
 */

Manager.prototype.maybeReconnectOnOpen = function() {
  // Only try to reconnect if it's the first time we're connecting
  if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) {
    // keeps reconnection from firing twice for the same reconnection loop
    this.reconnect();
  }
};


/**
 * Sets the current transport `socket`.
 *
 * @param {Function} optional, callback
 * @return {Manager} self
 * @api public
 */

Manager.prototype.open =
Manager.prototype.connect = function(fn){
  debug('readyState %s', this.readyState);
  if (~this.readyState.indexOf('open')) return this;

  debug('opening %s', this.uri);
  this.engine = eio(this.uri, this.opts);
  var socket = this.engine;
  var self = this;
  this.readyState = 'opening';
  this.skipReconnect = false;

  // emit `open`
  var openSub = on(socket, 'open', function() {
    self.onopen();
    fn && fn();
  });

  // emit `connect_error`
  var errorSub = on(socket, 'error', function(data){
    debug('connect_error');
    self.cleanup();
    self.readyState = 'closed';
    self.emitAll('connect_error', data);
    if (fn) {
      var err = new Error('Connection error');
      err.data = data;
      fn(err);
    } else {
      // Only do this if there is no fn to handle the error
      self.maybeReconnectOnOpen();
    }
  });

  // emit `connect_timeout`
  if (false !== this._timeout) {
    var timeout = this._timeout;
    debug('connect attempt will timeout after %d', timeout);

    // set timer
    var timer = setTimeout(function(){
      debug('connect attempt timed out after %d', timeout);
      openSub.destroy();
      socket.close();
      socket.emit('error', 'timeout');
      self.emitAll('connect_timeout', timeout);
    }, timeout);

    this.subs.push({
      destroy: function(){
        clearTimeout(timer);
      }
    });
  }

  this.subs.push(openSub);
  this.subs.push(errorSub);

  return this;
};

/**
 * Called upon transport open.
 *
 * @api private
 */

Manager.prototype.onopen = function(){
  debug('open');

  // clear old subs
  this.cleanup();

  // mark as open
  this.readyState = 'open';
  this.emit('open');

  // add new subs
  var socket = this.engine;
  this.subs.push(on(socket, 'data', bind(this, 'ondata')));
  this.subs.push(on(socket, 'ping', bind(this, 'onping')));
  this.subs.push(on(socket, 'pong', bind(this, 'onpong')));
  this.subs.push(on(socket, 'error', bind(this, 'onerror')));
  this.subs.push(on(socket, 'close', bind(this, 'onclose')));
  this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded')));
};

/**
 * Called upon a ping.
 *
 * @api private
 */

Manager.prototype.onping = function(){
  this.lastPing = new Date;
  this.emitAll('ping');
};

/**
 * Called upon a packet.
 *
 * @api private
 */

Manager.prototype.onpong = function(){
  this.emitAll('pong', new Date - this.lastPing);
};

/**
 * Called with data.
 *
 * @api private
 */

Manager.prototype.ondata = function(data){
  this.decoder.add(data);
};

/**
 * Called when parser fully decodes a packet.
 *
 * @api private
 */

Manager.prototype.ondecoded = function(packet) {
  this.emit('packet', packet);
};

/**
 * Called upon socket error.
 *
 * @api private
 */

Manager.prototype.onerror = function(err){
  debug('error', err);
  this.emitAll('error', err);
};

/**
 * Creates a new socket for the given `nsp`.
 *
 * @return {Socket}
 * @api public
 */

Manager.prototype.socket = function(nsp){
  var socket = this.nsps[nsp];
  if (!socket) {
    socket = new Socket(this, nsp);
    this.nsps[nsp] = socket;
    var self = this;
    socket.on('connecting', onConnecting);
    socket.on('connect', function(){
      socket.id = self.engine.id;
    });

    if (this.autoConnect) {
      // manually call here since connecting evnet is fired before listening
      onConnecting();
    }
  }

  function onConnecting() {
    if (!~indexOf(self.connecting, socket)) {
      self.connecting.push(socket);
    }
  }

  return socket;
};

/**
 * Called upon a socket close.
 *
 * @param {Socket} socket
 */

Manager.prototype.destroy = function(socket){
  var index = indexOf(this.connecting, socket);
  if (~index) this.connecting.splice(index, 1);
  if (this.connecting.length) return;

  this.close();
};

/**
 * Writes a packet.
 *
 * @param {Object} packet
 * @api private
 */

Manager.prototype.packet = function(packet){
  debug('writing packet %j', packet);
  var self = this;

  if (!self.encoding) {
    // encode, then write to engine with result
    self.encoding = true;
    this.encoder.encode(packet, function(encodedPackets) {
      for (var i = 0; i < encodedPackets.length; i++) {
        self.engine.write(encodedPackets[i], packet.options);
      }
      self.encoding = false;
      self.processPacketQueue();
    });
  } else { // add packet to the queue
    self.packetBuffer.push(packet);
  }
};

/**
 * If packet buffer is non-empty, begins encoding the
 * next packet in line.
 *
 * @api private
 */

Manager.prototype.processPacketQueue = function() {
  if (this.packetBuffer.length > 0 && !this.encoding) {
    var pack = this.packetBuffer.shift();
    this.packet(pack);
  }
};

/**
 * Clean up transport subscriptions and packet buffer.
 *
 * @api private
 */

Manager.prototype.cleanup = function(){
  debug('cleanup');

  var sub;
  while (sub = this.subs.shift()) sub.destroy();

  this.packetBuffer = [];
  this.encoding = false;
  this.lastPing = null;

  this.decoder.destroy();
};

/**
 * Close the current socket.
 *
 * @api private
 */

Manager.prototype.close =
Manager.prototype.disconnect = function(){
  debug('disconnect');
  this.skipReconnect = true;
  this.reconnecting = false;
  if ('opening' == this.readyState) {
    // `onclose` will not fire because
    // an open event never happened
    this.cleanup();
  }
  this.backoff.reset();
  this.readyState = 'closed';
  if (this.engine) this.engine.close();
};

/**
 * Called upon engine close.
 *
 * @api private
 */

Manager.prototype.onclose = function(reason){
  debug('onclose');

  this.cleanup();
  this.backoff.reset();
  this.readyState = 'closed';
  this.emit('close', reason);

  if (this._reconnection && !this.skipReconnect) {
    this.reconnect();
  }
};

/**
 * Attempt a reconnection.
 *
 * @api private
 */

Manager.prototype.reconnect = function(){
  if (this.reconnecting || this.skipReconnect) return this;

  var self = this;

  if (this.backoff.attempts >= this._reconnectionAttempts) {
    debug('reconnect failed');
    this.backoff.reset();
    this.emitAll('reconnect_failed');
    this.reconnecting = false;
  } else {
    var delay = this.backoff.duration();
    debug('will wait %dms before reconnect attempt', delay);

    this.reconnecting = true;
    var timer = setTimeout(function(){
      if (self.skipReconnect) return;

      debug('attempting reconnect');
      self.emitAll('reconnect_attempt', self.backoff.attempts);
      self.emitAll('reconnecting', self.backoff.attempts);

      // check again for the case socket closed in above events
      if (self.skipReconnect) return;

      self.open(function(err){
        if (err) {
          debug('reconnect attempt error');
          self.reconnecting = false;
          self.reconnect();
          self.emitAll('reconnect_error', err.data);
        } else {
          debug('reconnect success');
          self.onreconnect();
        }
      });
    }, delay);

    this.subs.push({
      destroy: function(){
        clearTimeout(timer);
      }
    });
  }
};

/**
 * Called upon successful reconnect.
 *
 * @api private
 */

Manager.prototype.onreconnect = function(){
  var attempt = this.backoff.attempts;
  this.reconnecting = false;
  this.backoff.reset();
  this.updateSocketIds();
  this.emitAll('reconnect', attempt);
};

},{"./on":3,"./socket":4,"backo2":8,"component-bind":11,"component-emitter":12,"debug":14,"engine.io-client":16,"indexof":33,"socket.io-parser":41}],3:[function(_dereq_,module,exports){

/**
 * Module exports.
 */

module.exports = on;

/**
 * Helper for subscriptions.
 *
 * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter`
 * @param {String} event name
 * @param {Function} callback
 * @api public
 */

function on(obj, ev, fn) {
  obj.on(ev, fn);
  return {
    destroy: function(){
      obj.removeListener(ev, fn);
    }
  };
}

},{}],4:[function(_dereq_,module,exports){

/**
 * Module dependencies.
 */

var parser = _dereq_('socket.io-parser');
var Emitter = _dereq_('component-emitter');
var toArray = _dereq_('to-array');
var on = _dereq_('./on');
var bind = _dereq_('component-bind');
var debug = _dereq_('debug')('socket.io-client:socket');
var hasBin = _dereq_('has-binary');

/**
 * Module exports.
 */

module.exports = exports = Socket;

/**
 * Internal events (blacklisted).
 * These events can't be emitted by the user.
 *
 * @api private
 */

var events = {
  connect: 1,
  connect_error: 1,
  connect_timeout: 1,
  connecting: 1,
  disconnect: 1,
  error: 1,
  reconnect: 1,
  reconnect_attempt: 1,
  reconnect_failed: 1,
  reconnect_error: 1,
  reconnecting: 1,
  ping: 1,
  pong: 1
};

/**
 * Shortcut to `Emitter#emit`.
 */

var emit = Emitter.prototype.emit;

/**
 * `Socket` constructor.
 *
 * @api public
 */

function Socket(io, nsp){
  this.io = io;
  this.nsp = nsp;
  this.json = this; // compat
  this.ids = 0;
  this.acks = {};
  this.receiveBuffer = [];
  this.sendBuffer = [];
  this.connected = false;
  this.disconnected = true;
  if (this.io.autoConnect) this.open();
}

/**
 * Mix in `Emitter`.
 */

Emitter(Socket.prototype);

/**
 * Subscribe to open, close and packet events
 *
 * @api private
 */

Socket.prototype.subEvents = function() {
  if (this.subs) return;

  var io = this.io;
  this.subs = [
    on(io, 'open', bind(this, 'onopen')),
    on(io, 'packet', bind(this, 'onpacket')),
    on(io, 'close', bind(this, 'onclose'))
  ];
};

/**
 * "Opens" the socket.
 *
 * @api public
 */

Socket.prototype.open =
Socket.prototype.connect = function(){
  if (this.connected) return this;

  this.subEvents();
  this.io.open(); // ensure open
  if ('open' == this.io.readyState) this.onopen();
  this.emit('connecting');
  return this;
};

/**
 * Sends a `message` event.
 *
 * @return {Socket} self
 * @api public
 */

Socket.prototype.send = function(){
  var args = toArray(arguments);
  args.unshift('message');
  this.emit.apply(this, args);
  return this;
};

/**
 * Override `emit`.
 * If the event is in `events`, it's emitted normally.
 *
 * @param {String} event name
 * @return {Socket} self
 * @api public
 */

Socket.prototype.emit = function(ev){
  if (events.hasOwnProperty(ev)) {
    emit.apply(this, arguments);
    return this;
  }

  var args = toArray(arguments);
  var parserType = parser.EVENT; // default
  if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary
  var packet = { type: parserType, data: args };

  packet.options = {};
  packet.options.compress = !this.flags || false !== this.flags.compress;

  // event ack callback
  if ('function' == typeof args[args.length - 1]) {
    debug('emitting packet with ack id %d', this.ids);
    this.acks[this.ids] = args.pop();
    packet.id = this.ids++;
  }

  if (this.connected) {
    this.packet(packet);
  } else {
    this.sendBuffer.push(packet);
  }

  delete this.flags;

  return this;
};

/**
 * Sends a packet.
 *
 * @param {Object} packet
 * @api private
 */

Socket.prototype.packet = function(packet){
  packet.nsp = this.nsp;
  this.io.packet(packet);
};

/**
 * Called upon engine `open`.
 *
 * @api private
 */

Socket.prototype.onopen = function(){
  debug('transport is open - connecting');

  // write connect packet if necessary
  if ('/' != this.nsp) {
    this.packet({ type: parser.CONNECT });
  }
};

/**
 * Called upon engine `close`.
 *
 * @param {String} reason
 * @api private
 */

Socket.prototype.onclose = function(reason){
  debug('close (%s)', reason);
  this.connected = false;
  this.disconnected = true;
  delete this.id;
  this.emit('disconnect', reason);
};

/**
 * Called with socket packet.
 *
 * @param {Object} packet
 * @api private
 */

Socket.prototype.onpacket = function(packet){
  if (packet.nsp != this.nsp) return;

  switch (packet.type) {
    case parser.CONNECT:
      this.onconnect();
      break;

    case parser.EVENT:
      this.onevent(packet);
      break;

    case parser.BINARY_EVENT:
      this.onevent(packet);
      break;

    case parser.ACK:
      this.onack(packet);
      break;

    case parser.BINARY_ACK:
      this.onack(packet);
      break;

    case parser.DISCONNECT:
      this.ondisconnect();
      break;

    case parser.ERROR:
      this.emit('error', packet.data);
      break;
  }
};

/**
 * Called upon a server event.
 *
 * @param {Object} packet
 * @api private
 */

Socket.prototype.onevent = function(packet){
  var args = packet.data || [];
  debug('emitting event %j', args);

  if (null != packet.id) {
    debug('attaching ack callback to event');
    args.push(this.ack(packet.id));
  }

  if (this.connected) {
    emit.apply(this, args);
  } else {
    this.receiveBuffer.push(args);
  }
};

/**
 * Produces an ack callback to emit with an event.
 *
 * @api private
 */

Socket.prototype.ack = function(id){
  var self = this;
  var sent = false;
  return function(){
    // prevent double callbacks
    if (sent) return;
    sent = true;
    var args = toArray(arguments);
    debug('sending ack %j', args);

    var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK;
    self.packet({
      type: type,
      id: id,
      data: args
    });
  };
};

/**
 * Called upon a server acknowlegement.
 *
 * @param {Object} packet
 * @api private
 */

Socket.prototype.onack = function(packet){
  var ack = this.acks[packet.id];
  if ('function' == typeof ack) {
    debug('calling ack %s with %j', packet.id, packet.data);
    ack.apply(this, packet.data);
    delete this.acks[packet.id];
  } else {
    debug('bad ack %s', packet.id);
  }
};

/**
 * Called upon server connect.
 *
 * @api private
 */

Socket.prototype.onconnect = function(){
  this.connected = true;
  this.disconnected = false;
  this.emit('connect');
  this.emitBuffered();
};

/**
 * Emit buffered events (received and emitted).
 *
 * @api private
 */

Socket.prototype.emitBuffered = function(){
  var i;
  for (i = 0; i < this.receiveBuffer.length; i++) {
    emit.apply(this, this.receiveBuffer[i]);
  }
  this.receiveBuffer = [];

  for (i = 0; i < this.sendBuffer.length; i++) {
    this.packet(this.sendBuffer[i]);
  }
  this.sendBuffer = [];
};

/**
 * Called upon server disconnect.
 *
 * @api private
 */

Socket.prototype.ondisconnect = function(){
  debug('server disconnect (%s)', this.nsp);
  this.destroy();
  this.onclose('io server disconnect');
};

/**
 * Called upon forced client/server side disconnections,
 * this method ensures the manager stops tracking us and
 * that reconnections don't get triggered for this.
 *
 * @api private.
 */

Socket.prototype.destroy = function(){
  if (this.subs) {
    // clean subscriptions to avoid reconnections
    for (var i = 0; i < this.subs.length; i++) {
      this.subs[i].destroy();
    }
    this.subs = null;
  }

  this.io.destroy(this);
};

/**
 * Disconnects the socket manually.
 *
 * @return {Socket} self
 * @api public
 */

Socket.prototype.close =
Socket.prototype.disconnect = function(){
  if (this.connected) {
    debug('performing disconnect (%s)', this.nsp);
    this.packet({ type: parser.DISCONNECT });
  }

  // remove socket from pool
  this.destroy();

  if (this.connected) {
    // fire events
    this.onclose('io client disconnect');
  }
  return this;
};

/**
 * Sets the compress flag.
 *
 * @param {Boolean} if `true`, compresses the sending data
 * @return {Socket} self
 * @api public
 */

Socket.prototype.compress = function(compress){
  this.flags = this.flags || {};
  this.flags.compress = compress;
  return this;
};

},{"./on":3,"component-bind":11,"component-emitter":12,"debug":14,"has-binary":31,"socket.io-parser":41,"to-array":44}],5:[function(_dereq_,module,exports){
(function (global){

/**
 * Module dependencies.
 */

var parseuri = _dereq_('parseuri');
var debug = _dereq_('debug')('socket.io-client:url');

/**
 * Module exports.
 */

module.exports = url;

/**
 * URL parser.
 *
 * @param {String} url
 * @param {Object} An object meant to mimic window.location.
 *                 Defaults to window.location.
 * @api public
 */

function url(uri, loc){
  var obj = uri;

  // default to window.location
  var loc = loc || global.location;
  if (null == uri) uri = loc.protocol + '//' + loc.host;

  // relative path support
  if ('string' == typeof uri) {
    if ('/' == uri.charAt(0)) {
      if ('/' == uri.charAt(1)) {
        uri = loc.protocol + uri;
      } else {
        uri = loc.host + uri;
      }
    }

    if (!/^(https?|wss?):\/\//.test(uri)) {
      debug('protocol-less url %s', uri);
      if ('undefined' != typeof loc) {
        uri = loc.protocol + '//' + uri;
      } else {
        uri = 'https://' + uri;
      }
    }

    // parse
    debug('parse %s', uri);
    obj = parseuri(uri);
  }

  // make sure we treat `localhost:80` and `localhost` equally
  if (!obj.port) {
    if (/^(http|ws)$/.test(obj.protocol)) {
      obj.port = '80';
    }
    else if (/^(http|ws)s$/.test(obj.protocol)) {
      obj.port = '443';
    }
  }

  obj.path = obj.path || '/';

  var ipv6 = obj.host.indexOf(':') !== -1;
  var host = ipv6 ? '[' + obj.host + ']' : obj.host;

  // define unique id
  obj.id = obj.protocol + '://' + host + ':' + obj.port;
  // define href
  obj.href = obj.protocol + '://' + host + (loc && loc.port == obj.port ? '' : (':' + obj.port));

  return obj;
}

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"debug":14,"parseuri":39}],6:[function(_dereq_,module,exports){
module.exports = after

function after(count, callback, err_cb) {
    var bail = false
    err_cb = err_cb || noop
    proxy.count = count

    return (count === 0) ? callback() : proxy

    function proxy(err, result) {
        if (proxy.count <= 0) {
            throw new Error('after called too many times')
        }
        --proxy.count

        // after first error, rest are passed to err_cb
        if (err) {
            bail = true
            callback(err)
            // future error callbacks will go to error handler
            callback = err_cb
        } else if (proxy.count === 0 && !bail) {
            callback(null, result)
        }
    }
}

function noop() {}

},{}],7:[function(_dereq_,module,exports){
/**
 * An abstraction for slicing an arraybuffer even when
 * ArrayBuffer.prototype.slice is not supported
 *
 * @api public
 */

module.exports = function(arraybuffer, start, end) {
  var bytes = arraybuffer.byteLength;
  start = start || 0;
  end = end || bytes;

  if (arraybuffer.slice) { return arraybuffer.slice(start, end); }

  if (start < 0) { start += bytes; }
  if (end < 0) { end += bytes; }
  if (end > bytes) { end = bytes; }

  if (start >= bytes || start >= end || bytes === 0) {
    return new ArrayBuffer(0);
  }

  var abv = new Uint8Array(arraybuffer);
  var result = new Uint8Array(end - start);
  for (var i = start, ii = 0; i < end; i++, ii++) {
    result[ii] = abv[i];
  }
  return result.buffer;
};

},{}],8:[function(_dereq_,module,exports){

/**
 * Expose `Backoff`.
 */

module.exports = Backoff;

/**
 * Initialize backoff timer with `opts`.
 *
 * - `min` initial timeout in milliseconds [100]
 * - `max` max timeout [10000]
 * - `jitter` [0]
 * - `factor` [2]
 *
 * @param {Object} opts
 * @api public
 */

function Backoff(opts) {
  opts = opts || {};
  this.ms = opts.min || 100;
  this.max = opts.max || 10000;
  this.factor = opts.factor || 2;
  this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
  this.attempts = 0;
}

/**
 * Return the backoff duration.
 *
 * @return {Number}
 * @api public
 */

Backoff.prototype.duration = function(){
  var ms = this.ms * Math.pow(this.factor, this.attempts++);
  if (this.jitter) {
    var rand =  Math.random();
    var deviation = Math.floor(rand * this.jitter * ms);
    ms = (Math.floor(rand * 10) & 1) == 0  ? ms - deviation : ms + deviation;
  }
  return Math.min(ms, this.max) | 0;
};

/**
 * Reset the number of attempts.
 *
 * @api public
 */

Backoff.prototype.reset = function(){
  this.attempts = 0;
};

/**
 * Set the minimum duration
 *
 * @api public
 */

Backoff.prototype.setMin = function(min){
  this.ms = min;
};

/**
 * Set the maximum duration
 *
 * @api public
 */

Backoff.prototype.setMax = function(max){
  this.max = max;
};

/**
 * Set the jitter
 *
 * @api public
 */

Backoff.prototype.setJitter = function(jitter){
  this.jitter = jitter;
};


},{}],9:[function(_dereq_,module,exports){
/*
 * base64-arraybuffer
 * https://github.com/niklasvh/base64-arraybuffer
 *
 * Copyright (c) 2012 Niklas von Hertzen
 * Licensed under the MIT license.
 */
(function(chars){
  "use strict";

  exports.encode = function(arraybuffer) {
    var bytes = new Uint8Array(arraybuffer),
    i, len = bytes.buffer.byteLength, base64 = "";

    for (i = 0; i < len; i+=3) {
      base64 += chars[bytes.buffer[i] >> 2];
      base64 += chars[((bytes.buffer[i] & 3) << 4) | (bytes.buffer[i + 1] >> 4)];
      base64 += chars[((bytes.buffer[i + 1] & 15) << 2) | (bytes.buffer[i + 2] >> 6)];
      base64 += chars[bytes.buffer[i + 2] & 63];
    }

    if ((len % 3) === 2) {
      base64 = base64.substring(0, base64.length - 1) + "=";
    } else if (len % 3 === 1) {
      base64 = base64.substring(0, base64.length - 2) + "==";
    }

    return base64;
  };

  exports.decode =  function(base64) {
    var bufferLength = base64.length * 0.75,
    len = base64.length, i, p = 0,
    encoded1, encoded2, encoded3, encoded4;

    if (base64[base64.length - 1] === "=") {
      bufferLength--;
      if (base64[base64.length - 2] === "=") {
        bufferLength--;
      }
    }

    var arraybuffer = new ArrayBuffer(bufferLength),
    bytes = new Uint8Array(arraybuffer);

    for (i = 0; i < len; i+=4) {
      encoded1 = chars.indexOf(base64[i]);
      encoded2 = chars.indexOf(base64[i+1]);
      encoded3 = chars.indexOf(base64[i+2]);
      encoded4 = chars.indexOf(base64[i+3]);

      bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
      bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
      bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
    }

    return arraybuffer;
  };
})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
},{}],10:[function(_dereq_,module,exports){
(function (global){
/**
 * Create a blob builder even when vendor prefixes exist
 */

var BlobBuilder = global.BlobBuilder
  || global.WebKitBlobBuilder
  || global.MSBlobBuilder
  || global.MozBlobBuilder;

/**
 * Check if Blob constructor is supported
 */

var blobSupported = (function() {
  try {
    var a = new Blob(['hi']);
    return a.size === 2;
  } catch(e) {
    return false;
  }
})();

/**
 * Check if Blob constructor supports ArrayBufferViews
 * Fails in Safari 6, so we need to map to ArrayBuffers there.
 */

var blobSupportsArrayBufferView = blobSupported && (function() {
  try {
    var b = new Blob([new Uint8Array([1,2])]);
    return b.size === 2;
  } catch(e) {
    return false;
  }
})();

/**
 * Check if BlobBuilder is supported
 */

var blobBuilderSupported = BlobBuilder
  && BlobBuilder.prototype.append
  && BlobBuilder.prototype.getBlob;

/**
 * Helper function that maps ArrayBufferViews to ArrayBuffers
 * Used by BlobBuilder constructor and old browsers that didn't
 * support it in the Blob constructor.
 */

function mapArrayBufferViews(ary) {
  for (var i = 0; i < ary.length; i++) {
    var chunk = ary[i];
    if (chunk.buffer instanceof ArrayBuffer) {
      var buf = chunk.buffer;

      // if this is a subarray, make a copy so we only
      // include the subarray region from the underlying buffer
      if (chunk.byteLength !== buf.byteLength) {
        var copy = new Uint8Array(chunk.byteLength);
        copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
        buf = copy.buffer;
      }

      ary[i] = buf;
    }
  }
}

function BlobBuilderConstructor(ary, options) {
  options = options || {};

  var bb = new BlobBuilder();
  mapArrayBufferViews(ary);

  for (var i = 0; i < ary.length; i++) {
    bb.append(ary[i]);
  }

  return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
};

function BlobConstructor(ary, options) {
  mapArrayBufferViews(ary);
  return new Blob(ary, options || {});
};

module.exports = (function() {
  if (blobSupported) {
    return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
  } else if (blobBuilderSupported) {
    return BlobBuilderConstructor;
  } else {
    return undefined;
  }
})();

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{}],11:[function(_dereq_,module,exports){
/**
 * Slice reference.
 */

var slice = [].slice;

/**
 * Bind `obj` to `fn`.
 *
 * @param {Object} obj
 * @param {Function|String} fn or string
 * @return {Function}
 * @api public
 */

module.exports = function(obj, fn){
  if ('string' == typeof fn) fn = obj[fn];
  if ('function' != typeof fn) throw new Error('bind() requires a function');
  var args = slice.call(arguments, 2);
  return function(){
    return fn.apply(obj, args.concat(slice.call(arguments)));
  }
};

},{}],12:[function(_dereq_,module,exports){

/**
 * Expose `Emitter`.
 */

module.exports = Emitter;

/**
 * Initialize a new `Emitter`.
 *
 * @api public
 */

function Emitter(obj) {
  if (obj) return mixin(obj);
};

/**
 * Mixin the emitter properties.
 *
 * @param {Object} obj
 * @return {Object}
 * @api private
 */

function mixin(obj) {
  for (var key in Emitter.prototype) {
    obj[key] = Emitter.prototype[key];
  }
  return obj;
}

/**
 * Listen on the given `event` with `fn`.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
  this._callbacks = this._callbacks || {};
  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
    .push(fn);
  return this;
};

/**
 * Adds an `event` listener that will be invoked a single
 * time then automatically removed.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

Emitter.prototype.once = function(event, fn){
  function on() {
    this.off(event, on);
    fn.apply(this, arguments);
  }

  on.fn = fn;
  this.on(event, on);
  return this;
};

/**
 * Remove the given callback for `event` or all
 * registered callbacks.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
  this._callbacks = this._callbacks || {};

  // all
  if (0 == arguments.length) {
    this._callbacks = {};
    return this;
  }

  // specific event
  var callbacks = this._callbacks['$' + event];
  if (!callbacks) return this;

  // remove all handlers
  if (1 == arguments.length) {
    delete this._callbacks['$' + event];
    return this;
  }

  // remove specific handler
  var cb;
  for (var i = 0; i < callbacks.length; i++) {
    cb = callbacks[i];
    if (cb === fn || cb.fn === fn) {
      callbacks.splice(i, 1);
      break;
    }
  }
  return this;
};

/**
 * Emit `event` with the given args.
 *
 * @param {String} event
 * @param {Mixed} ...
 * @return {Emitter}
 */

Emitter.prototype.emit = function(event){
  this._callbacks = this._callbacks || {};
  var args = [].slice.call(arguments, 1)
    , callbacks = this._callbacks['$' + event];

  if (callbacks) {
    callbacks = callbacks.slice(0);
    for (var i = 0, len = callbacks.length; i < len; ++i) {
      callbacks[i].apply(this, args);
    }
  }

  return this;
};

/**
 * Return array of callbacks for `event`.
 *
 * @param {String} event
 * @return {Array}
 * @api public
 */

Emitter.prototype.listeners = function(event){
  this._callbacks = this._callbacks || {};
  return this._callbacks['$' + event] || [];
};

/**
 * Check if this emitter has `event` handlers.
 *
 * @param {String} event
 * @return {Boolean}
 * @api public
 */

Emitter.prototype.hasListeners = function(event){
  return !! this.listeners(event).length;
};

},{}],13:[function(_dereq_,module,exports){

module.exports = function(a, b){
  var fn = function(){};
  fn.prototype = b.prototype;
  a.prototype = new fn;
  a.prototype.constructor = a;
};
},{}],14:[function(_dereq_,module,exports){

/**
 * This is the web browser implementation of `debug()`.
 *
 * Expose `debug()` as the module.
 */

exports = module.exports = _dereq_('./debug');
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = 'undefined' != typeof chrome
               && 'undefined' != typeof chrome.storage
                  ? chrome.storage.local
                  : localstorage();

/**
 * Colors.
 */

exports.colors = [
  'lightseagreen',
  'forestgreen',
  'goldenrod',
  'dodgerblue',
  'darkorchid',
  'crimson'
];

/**
 * Currently only WebKit-based Web Inspectors, Firefox >= v31,
 * and the Firebug extension (any Firefox version) are known
 * to support "%c" CSS customizations.
 *
 * TODO: add a `localStorage` variable to explicitly enable/disable colors
 */

function useColors() {
  // is webkit? http://stackoverflow.com/a/16459606/376773
  return ('WebkitAppearance' in document.documentElement.style) ||
    // is firebug? http://stackoverflow.com/a/398120/376773
    (window.console && (console.firebug || (console.exception && console.table))) ||
    // is firefox >= v31?
    // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
    (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
}

/**
 * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
 */

exports.formatters.j = function(v) {
  return JSON.stringify(v);
};


/**
 * Colorize log arguments if enabled.
 *
 * @api public
 */

function formatArgs() {
  var args = arguments;
  var useColors = this.useColors;

  args[0] = (useColors ? '%c' : '')
    + this.namespace
    + (useColors ? ' %c' : ' ')
    + args[0]
    + (useColors ? '%c ' : ' ')
    + '+' + exports.humanize(this.diff);

  if (!useColors) return args;

  var c = 'color: ' + this.color;
  args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));

  // the final "%c" is somewhat tricky, because there could be other
  // arguments passed either before or after the %c, so we need to
  // figure out the correct index to insert the CSS into
  var index = 0;
  var lastC = 0;
  args[0].replace(/%[a-z%]/g, function(match) {
    if ('%%' === match) return;
    index++;
    if ('%c' === match) {
      // we only are interested in the *last* %c
      // (the user may have provided their own)
      lastC = index;
    }
  });

  args.splice(lastC, 0, c);
  return args;
}

/**
 * Invokes `console.log()` when available.
 * No-op when `console.log` is not a "function".
 *
 * @api public
 */

function log() {
  // this hackery is required for IE8/9, where
  // the `console.log` function doesn't have 'apply'
  return 'object' === typeof console
    && console.log
    && Function.prototype.apply.call(console.log, console, arguments);
}

/**
 * Save `namespaces`.
 *
 * @param {String} namespaces
 * @api private
 */

function save(namespaces) {
  try {
    if (null == namespaces) {
      exports.storage.removeItem('debug');
    } else {
      exports.storage.debug = namespaces;
    }
  } catch(e) {}
}

/**
 * Load `namespaces`.
 *
 * @return {String} returns the previously persisted debug modes
 * @api private
 */

function load() {
  var r;
  try {
    r = exports.storage.debug;
  } catch(e) {}
  return r;
}

/**
 * Enable namespaces listed in `localStorage.debug` initially.
 */

exports.enable(load());

/**
 * Localstorage attempts to return the localstorage.
 *
 * This is necessary because safari throws
 * when a user disables cookies/localstorage
 * and you attempt to access it.
 *
 * @return {LocalStorage}
 * @api private
 */

function localstorage(){
  try {
    return window.localStorage;
  } catch (e) {}
}

},{"./debug":15}],15:[function(_dereq_,module,exports){

/**
 * This is the common logic for both the Node.js and web browser
 * implementations of `debug()`.
 *
 * Expose `debug()` as the module.
 */

exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = _dereq_('ms');

/**
 * The currently active debug mode names, and names to skip.
 */

exports.names = [];
exports.skips = [];

/**
 * Map of special "%n" handling functions, for the debug "format" argument.
 *
 * Valid key names are a single, lowercased letter, i.e. "n".
 */

exports.formatters = {};

/**
 * Previously assigned color.
 */

var prevColor = 0;

/**
 * Previous log timestamp.
 */

var prevTime;

/**
 * Select a color.
 *
 * @return {Number}
 * @api private
 */

function selectColor() {
  return exports.colors[prevColor++ % exports.colors.length];
}

/**
 * Create a debugger with the given `namespace`.
 *
 * @param {String} namespace
 * @return {Function}
 * @api public
 */

function debug(namespace) {

  // define the `disabled` version
  function disabled() {
  }
  disabled.enabled = false;

  // define the `enabled` version
  function enabled() {

    var self = enabled;

    // set `diff` timestamp
    var curr = +new Date();
    var ms = curr - (prevTime || curr);
    self.diff = ms;
    self.prev = prevTime;
    self.curr = curr;
    prevTime = curr;

    // add the `color` if not set
    if (null == self.useColors) self.useColors = exports.useColors();
    if (null == self.color && self.useColors) self.color = selectColor();

    var args = Array.prototype.slice.call(arguments);

    args[0] = exports.coerce(args[0]);

    if ('string' !== typeof args[0]) {
      // anything else let's inspect with %o
      args = ['%o'].concat(args);
    }

    // apply any `formatters` transformations
    var index = 0;
    args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
      // if we encounter an escaped % then don't increase the array index
      if (match === '%%') return match;
      index++;
      var formatter = exports.formatters[format];
      if ('function' === typeof formatter) {
        var val = args[index];
        match = formatter.call(self, val);

        // now we need to remove `args[index]` since it's inlined in the `format`
        args.splice(index, 1);
        index--;
      }
      return match;
    });

    if ('function' === typeof exports.formatArgs) {
      args = exports.formatArgs.apply(self, args);
    }
    var logFn = enabled.log || exports.log || console.log.bind(console);
    logFn.apply(self, args);
  }
  enabled.enabled = true;

  var fn = exports.enabled(namespace) ? enabled : disabled;

  fn.namespace = namespace;

  return fn;
}

/**
 * Enables a debug mode by namespaces. This can include modes
 * separated by a colon and wildcards.
 *
 * @param {String} namespaces
 * @api public
 */

function enable(namespaces) {
  exports.save(namespaces);

  var split = (namespaces || '').split(/[\s,]+/);
  var len = split.length;

  for (var i = 0; i < len; i++) {
    if (!split[i]) continue; // ignore empty strings
    namespaces = split[i].replace(/\*/g, '.*?');
    if (namespaces[0] === '-') {
      exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
    } else {
      exports.names.push(new RegExp('^' + namespaces + '$'));
    }
  }
}

/**
 * Disable debug output.
 *
 * @api public
 */

function disable() {
  exports.enable('');
}

/**
 * Returns true if the given mode name is enabled, false otherwise.
 *
 * @param {String} name
 * @return {Boolean}
 * @api public
 */

function enabled(name) {
  var i, len;
  for (i = 0, len = exports.skips.length; i < len; i++) {
    if (exports.skips[i].test(name)) {
      return false;
    }
  }
  for (i = 0, len = exports.names.length; i < len; i++) {
    if (exports.names[i].test(name)) {
      return true;
    }
  }
  return false;
}

/**
 * Coerce `val`.
 *
 * @param {Mixed} val
 * @return {Mixed}
 * @api private
 */

function coerce(val) {
  if (val instanceof Error) return val.stack || val.message;
  return val;
}

},{"ms":36}],16:[function(_dereq_,module,exports){

module.exports =  _dereq_('./lib/');

},{"./lib/":17}],17:[function(_dereq_,module,exports){

module.exports = _dereq_('./socket');

/**
 * Exports parser
 *
 * @api public
 *
 */
module.exports.parser = _dereq_('engine.io-parser');

},{"./socket":18,"engine.io-parser":27}],18:[function(_dereq_,module,exports){
(function (global){
/**
 * Module dependencies.
 */

var transports = _dereq_('./transports');
var Emitter = _dereq_('component-emitter');
var debug = _dereq_('debug')('engine.io-client:socket');
var index = _dereq_('indexof');
var parser = _dereq_('engine.io-parser');
var parseuri = _dereq_('parseuri');
var parsejson = _dereq_('parsejson');
var parseqs = _dereq_('parseqs');

/**
 * Module exports.
 */

module.exports = Socket;

/**
 * Noop function.
 *
 * @api private
 */

function noop(){}

/**
 * Socket constructor.
 *
 * @param {String|Object} uri or options
 * @param {Object} options
 * @api public
 */

function Socket(uri, opts){
  if (!(this instanceof Socket)) return new Socket(uri, opts);

  opts = opts || {};

  if (uri && 'object' == typeof uri) {
    opts = uri;
    uri = null;
  }

  if (uri) {
    uri = parseuri(uri);
    opts.hostname = uri.host;
    opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
    opts.port = uri.port;
    if (uri.query) opts.query = uri.query;
  } else if (opts.host) {
    opts.hostname = parseuri(opts.host).host;
  }

  this.secure = null != opts.secure ? opts.secure :
    (global.location && 'https:' == location.protocol);

  if (opts.hostname && !opts.port) {
    // if no port is specified manually, use the protocol default
    opts.port = this.secure ? '443' : '80';
  }

  this.agent = opts.agent || false;
  this.hostname = opts.hostname ||
    (global.location ? location.hostname : 'localhost');
  this.port = opts.port || (global.location && location.port ?
       location.port :
       (this.secure ? 443 : 80));
  this.query = opts.query || {};
  if ('string' == typeof this.query) this.query = parseqs.decode(this.query);
  this.upgrade = false !== opts.upgrade;
  this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
  this.forceJSONP = !!opts.forceJSONP;
  this.jsonp = false !== opts.jsonp;
  this.forceBase64 = !!opts.forceBase64;
  this.enablesXDR = !!opts.enablesXDR;
  this.timestampParam = opts.timestampParam || 't';
  this.timestampRequests = opts.timestampRequests;
  this.transports = opts.transports || ['polling', 'websocket'];
  this.readyState = '';
  this.writeBuffer = [];
  this.policyPort = opts.policyPort || 843;
  this.rememberUpgrade = opts.rememberUpgrade || false;
  this.binaryType = null;
  this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
  this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false;

  if (true === this.perMessageDeflate) this.perMessageDeflate = {};
  if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) {
    this.perMessageDeflate.threshold = 1024;
  }

  // SSL options for Node.js client
  this.pfx = opts.pfx || null;
  this.key = opts.key || null;
  this.passphrase = opts.passphrase || null;
  this.cert = opts.cert || null;
  this.ca = opts.ca || null;
  this.ciphers = opts.ciphers || null;
  this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? null : opts.rejectUnauthorized;

  // other options for Node.js client
  var freeGlobal = typeof global == 'object' && global;
  if (freeGlobal.global === freeGlobal) {
    if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) {
      this.extraHeaders = opts.extraHeaders;
    }
  }

  this.open();
}

Socket.priorWebsocketSuccess = false;

/**
 * Mix in `Emitter`.
 */

Emitter(Socket.prototype);

/**
 * Protocol version.
 *
 * @api public
 */

Socket.protocol = parser.protocol; // this is an int

/**
 * Expose deps for legacy compatibility
 * and standalone browser access.
 */

Socket.Socket = Socket;
Socket.Transport = _dereq_('./transport');
Socket.transports = _dereq_('./transports');
Socket.parser = _dereq_('engine.io-parser');

/**
 * Creates transport of the given type.
 *
 * @param {String} transport name
 * @return {Transport}
 * @api private
 */

Socket.prototype.createTransport = function (name) {
  debug('creating transport "%s"', name);
  var query = clone(this.query);

  // append engine.io protocol identifier
  query.EIO = parser.protocol;

  // transport name
  query.transport = name;

  // session id if we already have one
  if (this.id) query.sid = this.id;

  var transport = new transports[name]({
    agent: this.agent,
    hostname: this.hostname,
    port: this.port,
    secure: this.secure,
    path: this.path,
    query: query,
    forceJSONP: this.forceJSONP,
    jsonp: this.jsonp,
    forceBase64: this.forceBase64,
    enablesXDR: this.enablesXDR,
    timestampRequests: this.timestampRequests,
    timestampParam: this.timestampParam,
    policyPort: this.policyPort,
    socket: this,
    pfx: this.pfx,
    key: this.key,
    passphrase: this.passphrase,
    cert: this.cert,
    ca: this.ca,
    ciphers: this.ciphers,
    rejectUnauthorized: this.rejectUnauthorized,
    perMessageDeflate: this.perMessageDeflate,
    extraHeaders: this.extraHeaders
  });

  return transport;
};

function clone (obj) {
  var o = {};
  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
      o[i] = obj[i];
    }
  }
  return o;
}

/**
 * Initializes transport to use and starts probe.
 *
 * @api private
 */
Socket.prototype.open = function () {
  var transport;
  if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
    transport = 'websocket';
  } else if (0 === this.transports.length) {
    // Emit error on next tick so it can be listened to
    var self = this;
    setTimeout(function() {
      self.emit('error', 'No transports available');
    }, 0);
    return;
  } else {
    transport = this.transports[0];
  }
  this.readyState = 'opening';

  // Retry with the next transport if the transport is disabled (jsonp: false)
  try {
    transport = this.createTransport(transport);
  } catch (e) {
    this.transports.shift();
    this.open();
    return;
  }

  transport.open();
  this.setTransport(transport);
};

/**
 * Sets the current transport. Disables the existing one (if any).
 *
 * @api private
 */

Socket.prototype.setTransport = function(transport){
  debug('setting transport %s', transport.name);
  var self = this;

  if (this.transport) {
    debug('clearing existing transport %s', this.transport.name);
    this.transport.removeAllListeners();
  }

  // set up transport
  this.transport = transport;

  // set up transport listeners
  transport
  .on('drain', function(){
    self.onDrain();
  })
  .on('packet', function(packet){
    self.onPacket(packet);
  })
  .on('error', function(e){
    self.onError(e);
  })
  .on('close', function(){
    self.onClose('transport close');
  });
};

/**
 * Probes a transport.
 *
 * @param {String} transport name
 * @api private
 */

Socket.prototype.probe = function (name) {
  debug('probing transport "%s"', name);
  var transport = this.createTransport(name, { probe: 1 })
    , failed = false
    , self = this;

  Socket.priorWebsocketSuccess = false;

  function onTransportOpen(){
    if (self.onlyBinaryUpgrades) {
      var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
      failed = failed || upgradeLosesBinary;
    }
    if (failed) return;

    debug('probe transport "%s" opened', name);
    transport.send([{ type: 'ping', data: 'probe' }]);
    transport.once('packet', function (msg) {
      if (failed) return;
      if ('pong' == msg.type && 'probe' == msg.data) {
        debug('probe transport "%s" pong', name);
        self.upgrading = true;
        self.emit('upgrading', transport);
        if (!transport) return;
        Socket.priorWebsocketSuccess = 'websocket' == transport.name;

        debug('pausing current transport "%s"', self.transport.name);
        self.transport.pause(function () {
          if (failed) return;
          if ('closed' == self.readyState) return;
          debug('changing transport and sending upgrade packet');

          cleanup();

          self.setTransport(transport);
          transport.send([{ type: 'upgrade' }]);
          self.emit('upgrade', transport);
          transport = null;
          self.upgrading = false;
          self.flush();
        });
      } else {
        debug('probe transport "%s" failed', name);
        var err = new Error('probe error');
        err.transport = transport.name;
        self.emit('upgradeError', err);
      }
    });
  }

  function freezeTransport() {
    if (failed) return;

    // Any callback called by transport should be ignored since now
    failed = true;

    cleanup();

    transport.close();
    transport = null;
  }

  //Handle any error that happens while probing
  function onerror(err) {
    var error = new Error('probe error: ' + err);
    error.transport = transport.name;

    freezeTransport();

    debug('probe transport "%s" failed because of error: %s', name, err);

    self.emit('upgradeError', error);
  }

  function onTransportClose(){
    onerror("transport closed");
  }

  //When the socket is closed while we're probing
  function onclose(){
    onerror("socket closed");
  }

  //When the socket is upgraded while we're probing
  function onupgrade(to){
    if (transport && to.name != transport.name) {
      debug('"%s" works - aborting "%s"', to.name, transport.name);
      freezeTransport();
    }
  }

  //Remove all listeners on the transport and on self
  function cleanup(){
    transport.removeListener('open', onTransportOpen);
    transport.removeListener('error', onerror);
    transport.removeListener('close', onTransportClose);
    self.removeListener('close', onclose);
    self.removeListener('upgrading', onupgrade);
  }

  transport.once('open', onTransportOpen);
  transport.once('error', onerror);
  transport.once('close', onTransportClose);

  this.once('close', onclose);
  this.once('upgrading', onupgrade);

  transport.open();

};

/**
 * Called when connection is deemed open.
 *
 * @api public
 */

Socket.prototype.onOpen = function () {
  debug('socket open');
  this.readyState = 'open';
  Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
  this.emit('open');
  this.flush();

  // we check for `readyState` in case an `open`
  // listener already closed the socket
  if ('open' == this.readyState && this.upgrade && this.transport.pause) {
    debug('starting upgrade probes');
    for (var i = 0, l = this.upgrades.length; i < l; i++) {
      this.probe(this.upgrades[i]);
    }
  }
};

/**
 * Handles a packet.
 *
 * @api private
 */

Socket.prototype.onPacket = function (packet) {
  if ('opening' == this.readyState || 'open' == this.readyState) {
    debug('socket receive: type "%s", data "%s"', packet.type, packet.data);

    this.emit('packet', packet);

    // Socket is live - any packet counts
    this.emit('heartbeat');

    switch (packet.type) {
      case 'open':
        this.onHandshake(parsejson(packet.data));
        break;

      case 'pong':
        this.setPing();
        this.emit('pong');
        break;

      case 'error':
        var err = new Error('server error');
        err.code = packet.data;
        this.onError(err);
        break;

      case 'message':
        this.emit('data', packet.data);
        this.emit('message', packet.data);
        break;
    }
  } else {
    debug('packet received with socket readyState "%s"', this.readyState);
  }
};

/**
 * Called upon handshake completion.
 *
 * @param {Object} handshake obj
 * @api private
 */

Socket.prototype.onHandshake = function (data) {
  this.emit('handshake', data);
  this.id = data.sid;
  this.transport.query.sid = data.sid;
  this.upgrades = this.filterUpgrades(data.upgrades);
  this.pingInterval = data.pingInterval;
  this.pingTimeout = data.pingTimeout;
  this.onOpen();
  // In case open handler closes socket
  if  ('closed' == this.readyState) return;
  this.setPing();

  // Prolong liveness of socket on heartbeat
  this.removeListener('heartbeat', this.onHeartbeat);
  this.on('heartbeat', this.onHeartbeat);
};

/**
 * Resets ping timeout.
 *
 * @api private
 */

Socket.prototype.onHeartbeat = function (timeout) {
  clearTimeout(this.pingTimeoutTimer);
  var self = this;
  self.pingTimeoutTimer = setTimeout(function () {
    if ('closed' == self.readyState) return;
    self.onClose('ping timeout');
  }, timeout || (self.pingInterval + self.pingTimeout));
};

/**
 * Pings server every `this.pingInterval` and expects response
 * within `this.pingTimeout` or closes connection.
 *
 * @api private
 */

Socket.prototype.setPing = function () {
  var self = this;
  clearTimeout(self.pingIntervalTimer);
  self.pingIntervalTimer = setTimeout(function () {
    debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
    self.ping();
    self.onHeartbeat(self.pingTimeout);
  }, self.pingInterval);
};

/**
* Sends a ping packet.
*
* @api private
*/

Socket.prototype.ping = function () {
  var self = this;
  this.sendPacket('ping', function(){
    self.emit('ping');
  });
};

/**
 * Called on `drain` event
 *
 * @api private
 */

Socket.prototype.onDrain = function() {
  this.writeBuffer.splice(0, this.prevBufferLen);

  // setting prevBufferLen = 0 is very important
  // for example, when upgrading, upgrade packet is sent over,
  // and a nonzero prevBufferLen could cause problems on `drain`
  this.prevBufferLen = 0;

  if (0 === this.writeBuffer.length) {
    this.emit('drain');
  } else {
    this.flush();
  }
};

/**
 * Flush write buffers.
 *
 * @api private
 */

Socket.prototype.flush = function () {
  if ('closed' != this.readyState && this.transport.writable &&
    !this.upgrading && this.writeBuffer.length) {
    debug('flushing %d packets in socket', this.writeBuffer.length);
    this.transport.send(this.writeBuffer);
    // keep track of current length of writeBuffer
    // splice writeBuffer and callbackBuffer on `drain`
    this.prevBufferLen = this.writeBuffer.length;
    this.emit('flush');
  }
};

/**
 * Sends a message.
 *
 * @param {String} message.
 * @param {Function} callback function.
 * @param {Object} options.
 * @return {Socket} for chaining.
 * @api public
 */

Socket.prototype.write =
Socket.prototype.send = function (msg, options, fn) {
  this.sendPacket('message', msg, options, fn);
  return this;
};

/**
 * Sends a packet.
 *
 * @param {String} packet type.
 * @param {String} data.
 * @param {Object} options.
 * @param {Function} callback function.
 * @api private
 */

Socket.prototype.sendPacket = function (type, data, options, fn) {
  if('function' == typeof data) {
    fn = data;
    data = undefined;
  }

  if ('function' == typeof options) {
    fn = options;
    options = null;
  }

  if ('closing' == this.readyState || 'closed' == this.readyState) {
    return;
  }

  options = options || {};
  options.compress = false !== options.compress;

  var packet = {
    type: type,
    data: data,
    options: options
  };
  this.emit('packetCreate', packet);
  this.writeBuffer.push(packet);
  if (fn) this.once('flush', fn);
  this.flush();
};

/**
 * Closes the connection.
 *
 * @api private
 */

Socket.prototype.close = function () {
  if ('opening' == this.readyState || 'open' == this.readyState) {
    this.readyState = 'closing';

    var self = this;

    if (this.writeBuffer.length) {
      this.once('drain', function() {
        if (this.upgrading) {
          waitForUpgrade();
        } else {
          close();
        }
      });
    } else if (this.upgrading) {
      waitForUpgrade();
    } else {
      close();
    }
  }

  function close() {
    self.onClose('forced close');
    debug('socket closing - telling transport to close');
    self.transport.close();
  }

  function cleanupAndClose() {
    self.removeListener('upgrade', cleanupAndClose);
    self.removeListener('upgradeError', cleanupAndClose);
    close();
  }

  function waitForUpgrade() {
    // wait for upgrade to finish since we can't send packets while pausing a transport
    self.once('upgrade', cleanupAndClose);
    self.once('upgradeError', cleanupAndClose);
  }

  return this;
};

/**
 * Called upon transport error
 *
 * @api private
 */

Socket.prototype.onError = function (err) {
  debug('socket error %j', err);
  Socket.priorWebsocketSuccess = false;
  this.emit('error', err);
  this.onClose('transport error', err);
};

/**
 * Called upon transport close.
 *
 * @api private
 */

Socket.prototype.onClose = function (reason, desc) {
  if ('opening' == this.readyState || 'open' == this.readyState || 'closing' == this.readyState) {
    debug('socket close with reason: "%s"', reason);
    var self = this;

    // clear timers
    clearTimeout(this.pingIntervalTimer);
    clearTimeout(this.pingTimeoutTimer);

    // stop event from firing again for transport
    this.transport.removeAllListeners('close');

    // ensure transport won't stay open
    this.transport.close();

    // ignore further transport communication
    this.transport.removeAllListeners();

    // set ready state
    this.readyState = 'closed';

    // clear session id
    this.id = null;

    // emit close event
    this.emit('close', reason, desc);

    // clean buffers after, so users can still
    // grab the buffers on `close` event
    self.writeBuffer = [];
    self.prevBufferLen = 0;
  }
};

/**
 * Filters upgrades, returning only those matching client transports.
 *
 * @param {Array} server upgrades
 * @api private
 *
 */

Socket.prototype.filterUpgrades = function (upgrades) {
  var filteredUpgrades = [];
  for (var i = 0, j = upgrades.length; i<j; i++) {
    if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
  }
  return filteredUpgrades;
};

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"./transport":19,"./transports":20,"component-emitter":26,"debug":14,"engine.io-parser":27,"indexof":33,"parsejson":37,"parseqs":38,"parseuri":39}],19:[function(_dereq_,module,exports){
/**
 * Module dependencies.
 */

var parser = _dereq_('engine.io-parser');
var Emitter = _dereq_('component-emitter');

/**
 * Module exports.
 */

module.exports = Transport;

/**
 * Transport abstract constructor.
 *
 * @param {Object} options.
 * @api private
 */

function Transport (opts) {
  this.path = opts.path;
  this.hostname = opts.hostname;
  this.port = opts.port;
  this.secure = opts.secure;
  this.query = opts.query;
  this.timestampParam = opts.timestampParam;
  this.timestampRequests = opts.timestampRequests;
  this.readyState = '';
  this.agent = opts.agent || false;
  this.socket = opts.socket;
  this.enablesXDR = opts.enablesXDR;

  // SSL options for Node.js client
  this.pfx = opts.pfx;
  this.key = opts.key;
  this.passphrase = opts.passphrase;
  this.cert = opts.cert;
  this.ca = opts.ca;
  this.ciphers = opts.ciphers;
  this.rejectUnauthorized = opts.rejectUnauthorized;

  // other options for Node.js client
  this.extraHeaders = opts.extraHeaders;
}

/**
 * Mix in `Emitter`.
 */

Emitter(Transport.prototype);

/**
 * Emits an error.
 *
 * @param {String} str
 * @return {Transport} for chaining
 * @api public
 */

Transport.prototype.onError = function (msg, desc) {
  var err = new Error(msg);
  err.type = 'TransportError';
  err.description = desc;
  this.emit('error', err);
  return this;
};

/**
 * Opens the transport.
 *
 * @api public
 */

Transport.prototype.open = function () {
  if ('closed' == this.readyState || '' == this.readyState) {
    this.readyState = 'opening';
    this.doOpen();
  }

  return this;
};

/**
 * Closes the transport.
 *
 * @api private
 */

Transport.prototype.close = function () {
  if ('opening' == this.readyState || 'open' == this.readyState) {
    this.doClose();
    this.onClose();
  }

  return this;
};

/**
 * Sends multiple packets.
 *
 * @param {Array} packets
 * @api private
 */

Transport.prototype.send = function(packets){
  if ('open' == this.readyState) {
    this.write(packets);
  } else {
    throw new Error('Transport not open');
  }
};

/**
 * Called upon open
 *
 * @api private
 */

Transport.prototype.onOpen = function () {
  this.readyState = 'open';
  this.writable = true;
  this.emit('open');
};

/**
 * Called with data.
 *
 * @param {String} data
 * @api private
 */

Transport.prototype.onData = function(data){
  var packet = parser.decodePacket(data, this.socket.binaryType);
  this.onPacket(packet);
};

/**
 * Called with a decoded packet.
 */

Transport.prototype.onPacket = function (packet) {
  this.emit('packet', packet);
};

/**
 * Called upon close.
 *
 * @api private
 */

Transport.prototype.onClose = function () {
  this.readyState = 'closed';
  this.emit('close');
};

},{"component-emitter":26,"engine.io-parser":27}],20:[function(_dereq_,module,exports){
(function (global){
/**
 * Module dependencies
 */

var XMLHttpRequest = _dereq_('xmlhttprequest-ssl');
var XHR = _dereq_('./polling-xhr');
var JSONP = _dereq_('./polling-jsonp');
var websocket = _dereq_('./websocket');

/**
 * Export transports.
 */

exports.polling = polling;
exports.websocket = websocket;

/**
 * Polling transport polymorphic constructor.
 * Decides on xhr vs jsonp based on feature detection.
 *
 * @api private
 */

function polling(opts){
  var xhr;
  var xd = false;
  var xs = false;
  var jsonp = false !== opts.jsonp;

  if (global.location) {
    var isSSL = 'https:' == location.protocol;
    var port = location.port;

    // some user agents have empty `location.port`
    if (!port) {
      port = isSSL ? 443 : 80;
    }

    xd = opts.hostname != location.hostname || port != opts.port;
    xs = opts.secure != isSSL;
  }

  opts.xdomain = xd;
  opts.xscheme = xs;
  xhr = new XMLHttpRequest(opts);

  if ('open' in xhr && !opts.forceJSONP) {
    return new XHR(opts);
  } else {
    if (!jsonp) throw new Error('JSONP disabled');
    return new JSONP(opts);
  }
}

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"./polling-jsonp":21,"./polling-xhr":22,"./websocket":24,"xmlhttprequest-ssl":25}],21:[function(_dereq_,module,exports){
(function (global){

/**
 * Module requirements.
 */

var Polling = _dereq_('./polling');
var inherit = _dereq_('component-inherit');

/**
 * Module exports.
 */

module.exports = JSONPPolling;

/**
 * Cached regular expressions.
 */

var rNewline = /\n/g;
var rEscapedNewline = /\\n/g;

/**
 * Global JSONP callbacks.
 */

var callbacks;

/**
 * Callbacks count.
 */

var index = 0;

/**
 * Noop.
 */

function empty () { }

/**
 * JSONP Polling constructor.
 *
 * @param {Object} opts.
 * @api public
 */

function JSONPPolling (opts) {
  Polling.call(this, opts);

  this.query = this.query || {};

  // define global callbacks array if not present
  // we do this here (lazily) to avoid unneeded global pollution
  if (!callbacks) {
    // we need to consider multiple engines in the same page
    if (!global.___eio) global.___eio = [];
    callbacks = global.___eio;
  }

  // callback identifier
  this.index = callbacks.length;

  // add callback to jsonp global
  var self = this;
  callbacks.push(function (msg) {
    self.onData(msg);
  });

  // append to query string
  this.query.j = this.index;

  // prevent spurious errors from being emitted when the window is unloaded
  if (global.document && global.addEventListener) {
    global.addEventListener('beforeunload', function () {
      if (self.script) self.script.onerror = empty;
    }, false);
  }
}

/**
 * Inherits from Polling.
 */

inherit(JSONPPolling, Polling);

/*
 * JSONP only supports binary as base64 encoded strings
 */

JSONPPolling.prototype.supportsBinary = false;

/**
 * Closes the socket.
 *
 * @api private
 */

JSONPPolling.prototype.doClose = function () {
  if (this.script) {
    this.script.parentNode.removeChild(this.script);
    this.script = null;
  }

  if (this.form) {
    this.form.parentNode.removeChild(this.form);
    this.form = null;
    this.iframe = null;
  }

  Polling.prototype.doClose.call(this);
};

/**
 * Starts a poll cycle.
 *
 * @api private
 */

JSONPPolling.prototype.doPoll = function () {
  var self = this;
  var script = document.createElement('script');

  if (this.script) {
    this.script.parentNode.removeChild(this.script);
    this.script = null;
  }

  script.async = true;
  script.src = this.uri();
  script.onerror = function(e){
    self.onError('jsonp poll error',e);
  };

  var insertAt = document.getElementsByTagName('script')[0];
  insertAt.parentNode.insertBefore(script, insertAt);
  this.script = script;

  var isUAgecko = 'undefined' != typeof navigator && /gecko/i.test(navigator.userAgent);

  if (isUAgecko) {
    setTimeout(function () {
      var iframe = document.createElement('iframe');
      document.body.appendChild(iframe);
      document.body.removeChild(iframe);
    }, 100);
  }
};

/**
 * Writes with a hidden iframe.
 *
 * @param {String} data to send
 * @param {Function} called upon flush.
 * @api private
 */

JSONPPolling.prototype.doWrite = function (data, fn) {
  var self = this;

  if (!this.form) {
    var form = document.createElement('form');
    var area = document.createElement('textarea');
    var id = this.iframeId = 'eio_iframe_' + this.index;
    var iframe;

    form.className = 'socketio';
    form.style.position = 'absolute';
    form.style.top = '-1000px';
    form.style.left = '-1000px';
    form.target = id;
    form.method = 'POST';
    form.setAttribute('accept-charset', 'utf-8');
    area.name = 'd';
    form.appendChild(area);
    document.body.appendChild(form);

    this.form = form;
    this.area = area;
  }

  this.form.action = this.uri();

  function complete () {
    initIframe();
    fn();
  }

  function initIframe () {
    if (self.iframe) {
      try {
        self.form.removeChild(self.iframe);
      } catch (e) {
        self.onError('jsonp polling iframe removal error', e);
      }
    }

    try {
      // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
      var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">';
      iframe = document.createElement(html);
    } catch (e) {
      iframe = document.createElement('iframe');
      iframe.name = self.iframeId;
      iframe.src = 'javascript:0';
    }

    iframe.id = self.iframeId;

    self.form.appendChild(iframe);
    self.iframe = iframe;
  }

  initIframe();

  // escape \n to prevent it from being converted into \r\n by some UAs
  // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
  data = data.replace(rEscapedNewline, '\\\n');
  this.area.value = data.replace(rNewline, '\\n');

  try {
    this.form.submit();
  } catch(e) {}

  if (this.iframe.attachEvent) {
    this.iframe.onreadystatechange = function(){
      if (self.iframe.readyState == 'complete') {
        complete();
      }
    };
  } else {
    this.iframe.onload = complete;
  }
};

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"./polling":23,"component-inherit":13}],22:[function(_dereq_,module,exports){
(function (global){
/**
 * Module requirements.
 */

var XMLHttpRequest = _dereq_('xmlhttprequest-ssl');
var Polling = _dereq_('./polling');
var Emitter = _dereq_('component-emitter');
var inherit = _dereq_('component-inherit');
var debug = _dereq_('debug')('engine.io-client:polling-xhr');

/**
 * Module exports.
 */

module.exports = XHR;
module.exports.Request = Request;

/**
 * Empty function
 */

function empty(){}

/**
 * XHR Polling constructor.
 *
 * @param {Object} opts
 * @api public
 */

function XHR(opts){
  Polling.call(this, opts);

  if (global.location) {
    var isSSL = 'https:' == location.protocol;
    var port = location.port;

    // some user agents have empty `location.port`
    if (!port) {
      port = isSSL ? 443 : 80;
    }

    this.xd = opts.hostname != global.location.hostname ||
      port != opts.port;
    this.xs = opts.secure != isSSL;
  } else {
    this.extraHeaders = opts.extraHeaders;
  }
}

/**
 * Inherits from Polling.
 */

inherit(XHR, Polling);

/**
 * XHR supports binary
 */

XHR.prototype.supportsBinary = true;

/**
 * Creates a request.
 *
 * @param {String} method
 * @api private
 */

XHR.prototype.request = function(opts){
  opts = opts || {};
  opts.uri = this.uri();
  opts.xd = this.xd;
  opts.xs = this.xs;
  opts.agent = this.agent || false;
  opts.supportsBinary = this.supportsBinary;
  opts.enablesXDR = this.enablesXDR;

  // SSL options for Node.js client
  opts.pfx = this.pfx;
  opts.key = this.key;
  opts.passphrase = this.passphrase;
  opts.cert = this.cert;
  opts.ca = this.ca;
  opts.ciphers = this.ciphers;
  opts.rejectUnauthorized = this.rejectUnauthorized;

  // other options for Node.js client
  opts.extraHeaders = this.extraHeaders;

  return new Request(opts);
};

/**
 * Sends data.
 *
 * @param {String} data to send.
 * @param {Function} called upon flush.
 * @api private
 */

XHR.prototype.doWrite = function(data, fn){
  var isBinary = typeof data !== 'string' && data !== undefined;
  var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
  var self = this;
  req.on('success', fn);
  req.on('error', function(err){
    self.onError('xhr post error', err);
  });
  this.sendXhr = req;
};

/**
 * Starts a poll cycle.
 *
 * @api private
 */

XHR.prototype.doPoll = function(){
  debug('xhr poll');
  var req = this.request();
  var self = this;
  req.on('data', function(data){
    self.onData(data);
  });
  req.on('error', function(err){
    self.onError('xhr poll error', err);
  });
  this.pollXhr = req;
};

/**
 * Request constructor
 *
 * @param {Object} options
 * @api public
 */

function Request(opts){
  this.method = opts.method || 'GET';
  this.uri = opts.uri;
  this.xd = !!opts.xd;
  this.xs = !!opts.xs;
  this.async = false !== opts.async;
  this.data = undefined != opts.data ? opts.data : null;
  this.agent = opts.agent;
  this.isBinary = opts.isBinary;
  this.supportsBinary = opts.supportsBinary;
  this.enablesXDR = opts.enablesXDR;

  // SSL options for Node.js client
  this.pfx = opts.pfx;
  this.key = opts.key;
  this.passphrase = opts.passphrase;
  this.cert = opts.cert;
  this.ca = opts.ca;
  this.ciphers = opts.ciphers;
  this.rejectUnauthorized = opts.rejectUnauthorized;

  // other options for Node.js client
  this.extraHeaders = opts.extraHeaders;

  this.create();
}

/**
 * Mix in `Emitter`.
 */

Emitter(Request.prototype);

/**
 * Creates the XHR object and sends the request.
 *
 * @api private
 */

Request.prototype.create = function(){
  var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };

  // SSL options for Node.js client
  opts.pfx = this.pfx;
  opts.key = this.key;
  opts.passphrase = this.passphrase;
  opts.cert = this.cert;
  opts.ca = this.ca;
  opts.ciphers = this.ciphers;
  opts.rejectUnauthorized = this.rejectUnauthorized;

  var xhr = this.xhr = new XMLHttpRequest(opts);
  var self = this;

  try {
    debug('xhr open %s: %s', this.method, this.uri);
    xhr.open(this.method, this.uri, this.async);
    try {
      if (this.extraHeaders) {
        xhr.setDisableHeaderCheck(true);
        for (var i in this.extraHeaders) {
          if (this.extraHeaders.hasOwnProperty(i)) {
            xhr.setRequestHeader(i, this.extraHeaders[i]);
          }
        }
      }
    } catch (e) {}
    if (this.supportsBinary) {
      // This has to be done after open because Firefox is stupid
      // http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
      xhr.responseType = 'arraybuffer';
    }

    if ('POST' == this.method) {
      try {
        if (this.isBinary) {
          xhr.setRequestHeader('Content-type', 'application/octet-stream');
        } else {
          xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
        }
      } catch (e) {}
    }

    // ie6 check
    if ('withCredentials' in xhr) {
      xhr.withCredentials = true;
    }

    if (this.hasXDR()) {
      xhr.onload = function(){
        self.onLoad();
      };
      xhr.onerror = function(){
        self.onError(xhr.responseText);
      };
    } else {
      xhr.onreadystatechange = function(){
        if (4 != xhr.readyState) return;
        if (200 == xhr.status || 1223 == xhr.status) {
          self.onLoad();
        } else {
          // make sure the `error` event handler that's user-set
          // does not throw in the same tick and gets caught here
          setTimeout(function(){
            self.onError(xhr.status);
          }, 0);
        }
      };
    }

    debug('xhr data %s', this.data);
    xhr.send(this.data);
  } catch (e) {
    // Need to defer since .create() is called directly fhrom the constructor
    // and thus the 'error' event can only be only bound *after* this exception
    // occurs.  Therefore, also, we cannot throw here at all.
    setTimeout(function() {
      self.onError(e);
    }, 0);
    return;
  }

  if (global.document) {
    this.index = Request.requestsCount++;
    Request.requests[this.index] = this;
  }
};

/**
 * Called upon successful response.
 *
 * @api private
 */

Request.prototype.onSuccess = function(){
  this.emit('success');
  this.cleanup();
};

/**
 * Called if we have data.
 *
 * @api private
 */

Request.prototype.onData = function(data){
  this.emit('data', data);
  this.onSuccess();
};

/**
 * Called upon error.
 *
 * @api private
 */

Request.prototype.onError = function(err){
  this.emit('error', err);
  this.cleanup(true);
};

/**
 * Cleans up house.
 *
 * @api private
 */

Request.prototype.cleanup = function(fromError){
  if ('undefined' == typeof this.xhr || null === this.xhr) {
    return;
  }
  // xmlhttprequest
  if (this.hasXDR()) {
    this.xhr.onload = this.xhr.onerror = empty;
  } else {
    this.xhr.onreadystatechange = empty;
  }

  if (fromError) {
    try {
      this.xhr.abort();
    } catch(e) {}
  }

  if (global.document) {
    delete Request.requests[this.index];
  }

  this.xhr = null;
};

/**
 * Called upon load.
 *
 * @api private
 */

Request.prototype.onLoad = function(){
  var data;
  try {
    var contentType;
    try {
      contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0];
    } catch (e) {}
    if (contentType === 'application/octet-stream') {
      data = this.xhr.response;
    } else {
      if (!this.supportsBinary) {
        data = this.xhr.responseText;
      } else {
        try {
          data = String.fromCharCode.apply(null, new Uint8Array(this.xhr.response));
        } catch (e) {
          var ui8Arr = new Uint8Array(this.xhr.response);
          var dataArray = [];
          for (var idx = 0, length = ui8Arr.length; idx < length; idx++) {
            dataArray.push(ui8Arr[idx]);
          }

          data = String.fromCharCode.apply(null, dataArray);
        }
      }
    }
  } catch (e) {
    this.onError(e);
  }
  if (null != data) {
    this.onData(data);
  }
};

/**
 * Check if it has XDomainRequest.
 *
 * @api private
 */

Request.prototype.hasXDR = function(){
  return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
};

/**
 * Aborts the request.
 *
 * @api public
 */

Request.prototype.abort = function(){
  this.cleanup();
};

/**
 * Aborts pending requests when unloading the window. This is needed to prevent
 * memory leaks (e.g. when using IE) and to ensure that no spurious error is
 * emitted.
 */

if (global.document) {
  Request.requestsCount = 0;
  Request.requests = {};
  if (global.attachEvent) {
    global.attachEvent('onunload', unloadHandler);
  } else if (global.addEventListener) {
    global.addEventListener('beforeunload', unloadHandler, false);
  }
}

function unloadHandler() {
  for (var i in Request.requests) {
    if (Request.requests.hasOwnProperty(i)) {
      Request.requests[i].abort();
    }
  }
}

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"./polling":23,"component-emitter":26,"component-inherit":13,"debug":14,"xmlhttprequest-ssl":25}],23:[function(_dereq_,module,exports){
/**
 * Module dependencies.
 */

var Transport = _dereq_('../transport');
var parseqs = _dereq_('parseqs');
var parser = _dereq_('engine.io-parser');
var inherit = _dereq_('component-inherit');
var yeast = _dereq_('yeast');
var debug = _dereq_('debug')('engine.io-client:polling');

/**
 * Module exports.
 */

module.exports = Polling;

/**
 * Is XHR2 supported?
 */

var hasXHR2 = (function() {
  var XMLHttpRequest = _dereq_('xmlhttprequest-ssl');
  var xhr = new XMLHttpRequest({ xdomain: false });
  return null != xhr.responseType;
})();

/**
 * Polling interface.
 *
 * @param {Object} opts
 * @api private
 */

function Polling(opts){
  var forceBase64 = (opts && opts.forceBase64);
  if (!hasXHR2 || forceBase64) {
    this.supportsBinary = false;
  }
  Transport.call(this, opts);
}

/**
 * Inherits from Transport.
 */

inherit(Polling, Transport);

/**
 * Transport name.
 */

Polling.prototype.name = 'polling';

/**
 * Opens the socket (triggers polling). We write a PING message to determine
 * when the transport is open.
 *
 * @api private
 */

Polling.prototype.doOpen = function(){
  this.poll();
};

/**
 * Pauses polling.
 *
 * @param {Function} callback upon buffers are flushed and transport is paused
 * @api private
 */

Polling.prototype.pause = function(onPause){
  var pending = 0;
  var self = this;

  this.readyState = 'pausing';

  function pause(){
    debug('paused');
    self.readyState = 'paused';
    onPause();
  }

  if (this.polling || !this.writable) {
    var total = 0;

    if (this.polling) {
      debug('we are currently polling - waiting to pause');
      total++;
      this.once('pollComplete', function(){
        debug('pre-pause polling complete');
        --total || pause();
      });
    }

    if (!this.writable) {
      debug('we are currently writing - waiting to pause');
      total++;
      this.once('drain', function(){
        debug('pre-pause writing complete');
        --total || pause();
      });
    }
  } else {
    pause();
  }
};

/**
 * Starts polling cycle.
 *
 * @api public
 */

Polling.prototype.poll = function(){
  debug('polling');
  this.polling = true;
  this.doPoll();
  this.emit('poll');
};

/**
 * Overloads onData to detect payloads.
 *
 * @api private
 */

Polling.prototype.onData = function(data){
  var self = this;
  debug('polling got data %s', data);
  var callback = function(packet, index, total) {
    // if its the first message we consider the transport open
    if ('opening' == self.readyState) {
      self.onOpen();
    }

    // if its a close packet, we close the ongoing requests
    if ('close' == packet.type) {
      self.onClose();
      return false;
    }

    // otherwise bypass onData and handle the message
    self.onPacket(packet);
  };

  // decode payload
  parser.decodePayload(data, this.socket.binaryType, callback);

  // if an event did not trigger closing
  if ('closed' != this.readyState) {
    // if we got data we're not polling
    this.polling = false;
    this.emit('pollComplete');

    if ('open' == this.readyState) {
      this.poll();
    } else {
      debug('ignoring poll - transport state "%s"', this.readyState);
    }
  }
};

/**
 * For polling, send a close packet.
 *
 * @api private
 */

Polling.prototype.doClose = function(){
  var self = this;

  function close(){
    debug('writing close packet');
    self.write([{ type: 'close' }]);
  }

  if ('open' == this.readyState) {
    debug('transport open - closing');
    close();
  } else {
    // in case we're trying to close while
    // handshaking is in progress (GH-164)
    debug('transport not open - deferring close');
    this.once('open', close);
  }
};

/**
 * Writes a packets payload.
 *
 * @param {Array} data packets
 * @param {Function} drain callback
 * @api private
 */

Polling.prototype.write = function(packets){
  var self = this;
  this.writable = false;
  var callbackfn = function() {
    self.writable = true;
    self.emit('drain');
  };

  var self = this;
  parser.encodePayload(packets, this.supportsBinary, function(data) {
    self.doWrite(data, callbackfn);
  });
};

/**
 * Generates uri for connection.
 *
 * @api private
 */

Polling.prototype.uri = function(){
  var query = this.query || {};
  var schema = this.secure ? 'https' : 'http';
  var port = '';

  // cache busting is forced
  if (false !== this.timestampRequests) {
    query[this.timestampParam] = yeast();
  }

  if (!this.supportsBinary && !query.sid) {
    query.b64 = 1;
  }

  query = parseqs.encode(query);

  // avoid port if default for schema
  if (this.port && (('https' == schema && this.port != 443) ||
     ('http' == schema && this.port != 80))) {
    port = ':' + this.port;
  }

  // prepend ? to query
  if (query.length) {
    query = '?' + query;
  }

  var ipv6 = this.hostname.indexOf(':') !== -1;
  return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
};

},{"../transport":19,"component-inherit":13,"debug":14,"engine.io-parser":27,"parseqs":38,"xmlhttprequest-ssl":25,"yeast":46}],24:[function(_dereq_,module,exports){
(function (global){
/**
 * Module dependencies.
 */

var Transport = _dereq_('../transport');
var parser = _dereq_('engine.io-parser');
var parseqs = _dereq_('parseqs');
var inherit = _dereq_('component-inherit');
var yeast = _dereq_('yeast');
var debug = _dereq_('debug')('engine.io-client:websocket');
var BrowserWebSocket = global.WebSocket || global.MozWebSocket;

/**
 * Get either the `WebSocket` or `MozWebSocket` globals
 * in the browser or the WebSocket-compatible interface
 * exposed by `ws` for Node environment.
 */

var WebSocket = BrowserWebSocket || (typeof window !== 'undefined' ? null : _dereq_('ws'));

/**
 * Module exports.
 */

module.exports = WS;

/**
 * WebSocket transport constructor.
 *
 * @api {Object} connection options
 * @api public
 */

function WS(opts){
  var forceBase64 = (opts && opts.forceBase64);
  if (forceBase64) {
    this.supportsBinary = false;
  }
  this.perMessageDeflate = opts.perMessageDeflate;
  Transport.call(this, opts);
}

/**
 * Inherits from Transport.
 */

inherit(WS, Transport);

/**
 * Transport name.
 *
 * @api public
 */

WS.prototype.name = 'websocket';

/*
 * WebSockets support binary
 */

WS.prototype.supportsBinary = true;

/**
 * Opens socket.
 *
 * @api private
 */

WS.prototype.doOpen = function(){
  if (!this.check()) {
    // let probe timeout
    return;
  }

  var self = this;
  var uri = this.uri();
  var protocols = void(0);
  var opts = {
    agent: this.agent,
    perMessageDeflate: this.perMessageDeflate
  };

  // SSL options for Node.js client
  opts.pfx = this.pfx;
  opts.key = this.key;
  opts.passphrase = this.passphrase;
  opts.cert = this.cert;
  opts.ca = this.ca;
  opts.ciphers = this.ciphers;
  opts.rejectUnauthorized = this.rejectUnauthorized;
  if (this.extraHeaders) {
    opts.headers = this.extraHeaders;
  }

  this.ws = BrowserWebSocket ? new WebSocket(uri) : new WebSocket(uri, protocols, opts);

  if (this.ws.binaryType === undefined) {
    this.supportsBinary = false;
  }

  if (this.ws.supports && this.ws.supports.binary) {
    this.supportsBinary = true;
    this.ws.binaryType = 'buffer';
  } else {
    this.ws.binaryType = 'arraybuffer';
  }

  this.addEventListeners();
};

/**
 * Adds event listeners to the socket
 *
 * @api private
 */

WS.prototype.addEventListeners = function(){
  var self = this;

  this.ws.onopen = function(){
    self.onOpen();
  };
  this.ws.onclose = function(){
    self.onClose();
  };
  this.ws.onmessage = function(ev){
    self.onData(ev.data);
  };
  this.ws.onerror = function(e){
    self.onError('websocket error', e);
  };
};

/**
 * Override `onData` to use a timer on iOS.
 * See: https://gist.github.com/mloughran/2052006
 *
 * @api private
 */

if ('undefined' != typeof navigator
  && /iPad|iPhone|iPod/i.test(navigator.userAgent)) {
  WS.prototype.onData = function(data){
    var self = this;
    setTimeout(function(){
      Transport.prototype.onData.call(self, data);
    }, 0);
  };
}

/**
 * Writes data to socket.
 *
 * @param {Array} array of packets.
 * @api private
 */

WS.prototype.write = function(packets){
  var self = this;
  this.writable = false;

  // encodePacket efficient as it uses WS framing
  // no need for encodePayload
  var total = packets.length;
  for (var i = 0, l = total; i < l; i++) {
    (function(packet) {
      parser.encodePacket(packet, self.supportsBinary, function(data) {
        if (!BrowserWebSocket) {
          // always create a new object (GH-437)
          var opts = {};
          if (packet.options) {
            opts.compress = packet.options.compress;
          }

          if (self.perMessageDeflate) {
            var len = 'string' == typeof data ? global.Buffer.byteLength(data) : data.length;
            if (len < self.perMessageDeflate.threshold) {
              opts.compress = false;
            }
          }
        }

        //Sometimes the websocket has already been closed but the browser didn't
        //have a chance of informing us about it yet, in that case send will
        //throw an error
        try {
          if (BrowserWebSocket) {
            // TypeError is thrown when passing the second argument on Safari
            self.ws.send(data);
          } else {
            self.ws.send(data, opts);
          }
        } catch (e){
          debug('websocket closed before onclose event');
        }

        --total || done();
      });
    })(packets[i]);
  }

  function done(){
    self.emit('flush');

    // fake drain
    // defer to next tick to allow Socket to clear writeBuffer
    setTimeout(function(){
      self.writable = true;
      self.emit('drain');
    }, 0);
  }
};

/**
 * Called upon close
 *
 * @api private
 */

WS.prototype.onClose = function(){
  Transport.prototype.onClose.call(this);
};

/**
 * Closes socket.
 *
 * @api private
 */

WS.prototype.doClose = function(){
  if (typeof this.ws !== 'undefined') {
    this.ws.close();
  }
};

/**
 * Generates uri for connection.
 *
 * @api private
 */

WS.prototype.uri = function(){
  var query = this.query || {};
  var schema = this.secure ? 'wss' : 'ws';
  var port = '';

  // avoid port if default for schema
  if (this.port && (('wss' == schema && this.port != 443)
    || ('ws' == schema && this.port != 80))) {
    port = ':' + this.port;
  }

  // append timestamp to URI
  if (this.timestampRequests) {
    query[this.timestampParam] = yeast();
  }

  // communicate binary support capabilities
  if (!this.supportsBinary) {
    query.b64 = 1;
  }

  query = parseqs.encode(query);

  // prepend ? to query
  if (query.length) {
    query = '?' + query;
  }

  var ipv6 = this.hostname.indexOf(':') !== -1;
  return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query;
};

/**
 * Feature detection for WebSocket.
 *
 * @return {Boolean} whether this transport is available.
 * @api public
 */

WS.prototype.check = function(){
  return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
};

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"../transport":19,"component-inherit":13,"debug":14,"engine.io-parser":27,"parseqs":38,"ws":undefined,"yeast":46}],25:[function(_dereq_,module,exports){
// browser shim for xmlhttprequest module
var hasCORS = _dereq_('has-cors');

module.exports = function(opts) {
  var xdomain = opts.xdomain;

  // scheme must be same when usign XDomainRequest
  // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
  var xscheme = opts.xscheme;

  // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default.
  // https://github.com/Automattic/engine.io-client/pull/217
  var enablesXDR = opts.enablesXDR;

  // XMLHttpRequest can be disabled on IE
  try {
    if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) {
      return new XMLHttpRequest();
    }
  } catch (e) { }

  // Use XDomainRequest for IE8 if enablesXDR is true
  // because loading bar keeps flashing when using jsonp-polling
  // https://github.com/yujiosaka/socke.io-ie8-loading-example
  try {
    if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) {
      return new XDomainRequest();
    }
  } catch (e) { }

  if (!xdomain) {
    try {
      return new ActiveXObject('Microsoft.XMLHTTP');
    } catch(e) { }
  }
}

},{"has-cors":32}],26:[function(_dereq_,module,exports){

/**
 * Expose `Emitter`.
 */

module.exports = Emitter;

/**
 * Initialize a new `Emitter`.
 *
 * @api public
 */

function Emitter(obj) {
  if (obj) return mixin(obj);
};

/**
 * Mixin the emitter properties.
 *
 * @param {Object} obj
 * @return {Object}
 * @api private
 */

function mixin(obj) {
  for (var key in Emitter.prototype) {
    obj[key] = Emitter.prototype[key];
  }
  return obj;
}

/**
 * Listen on the given `event` with `fn`.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
  this._callbacks = this._callbacks || {};
  (this._callbacks[event] = this._callbacks[event] || [])
    .push(fn);
  return this;
};

/**
 * Adds an `event` listener that will be invoked a single
 * time then automatically removed.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

Emitter.prototype.once = function(event, fn){
  var self = this;
  this._callbacks = this._callbacks || {};

  function on() {
    self.off(event, on);
    fn.apply(this, arguments);
  }

  on.fn = fn;
  this.on(event, on);
  return this;
};

/**
 * Remove the given callback for `event` or all
 * registered callbacks.
 *
 * @param {String} event
 * @param {Function} fn
 * @return {Emitter}
 * @api public
 */

Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
  this._callbacks = this._callbacks || {};

  // all
  if (0 == arguments.length) {
    this._callbacks = {};
    return this;
  }

  // specific event
  var callbacks = this._callbacks[event];
  if (!callbacks) return this;

  // remove all handlers
  if (1 == arguments.length) {
    delete this._callbacks[event];
    return this;
  }

  // remove specific handler
  var cb;
  for (var i = 0; i < callbacks.length; i++) {
    cb = callbacks[i];
    if (cb === fn || cb.fn === fn) {
      callbacks.splice(i, 1);
      break;
    }
  }
  return this;
};

/**
 * Emit `event` with the given args.
 *
 * @param {String} event
 * @param {Mixed} ...
 * @return {Emitter}
 */

Emitter.prototype.emit = function(event){
  this._callbacks = this._callbacks || {};
  var args = [].slice.call(arguments, 1)
    , callbacks = this._callbacks[event];

  if (callbacks) {
    callbacks = callbacks.slice(0);
    for (var i = 0, len = callbacks.length; i < len; ++i) {
      callbacks[i].apply(this, args);
    }
  }

  return this;
};

/**
 * Return array of callbacks for `event`.
 *
 * @param {String} event
 * @return {Array}
 * @api public
 */

Emitter.prototype.listeners = function(event){
  this._callbacks = this._callbacks || {};
  return this._callbacks[event] || [];
};

/**
 * Check if this emitter has `event` handlers.
 *
 * @param {String} event
 * @return {Boolean}
 * @api public
 */

Emitter.prototype.hasListeners = function(event){
  return !! this.listeners(event).length;
};

},{}],27:[function(_dereq_,module,exports){
(function (global){
/**
 * Module dependencies.
 */

var keys = _dereq_('./keys');
var hasBinary = _dereq_('has-binary');
var sliceBuffer = _dereq_('arraybuffer.slice');
var base64encoder = _dereq_('base64-arraybuffer');
var after = _dereq_('after');
var utf8 = _dereq_('utf8');

/**
 * Check if we are running an android browser. That requires us to use
 * ArrayBuffer with polling transports...
 *
 * http://ghinda.net/jpeg-blob-ajax-android/
 */

var isAndroid = navigator.userAgent.match(/Android/i);

/**
 * Check if we are running in PhantomJS.
 * Uploading a Blob with PhantomJS does not work correctly, as reported here:
 * https://github.com/ariya/phantomjs/issues/11395
 * @type boolean
 */
var isPhantomJS = /PhantomJS/i.test(navigator.userAgent);

/**
 * When true, avoids using Blobs to encode payloads.
 * @type boolean
 */
var dontSendBlobs = isAndroid || isPhantomJS;

/**
 * Current protocol version.
 */

exports.protocol = 3;

/**
 * Packet types.
 */

var packets = exports.packets = {
    open:     0    // non-ws
  , close:    1    // non-ws
  , ping:     2
  , pong:     3
  , message:  4
  , upgrade:  5
  , noop:     6
};

var packetslist = keys(packets);

/**
 * Premade error packet.
 */

var err = { type: 'error', data: 'parser error' };

/**
 * Create a blob api even for blob builder when vendor prefixes exist
 */

var Blob = _dereq_('blob');

/**
 * Encodes a packet.
 *
 *     <packet type id> [ <data> ]
 *
 * Example:
 *
 *     5hello world
 *     3
 *     4
 *
 * Binary is encoded in an identical principle
 *
 * @api private
 */

exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) {
  if ('function' == typeof supportsBinary) {
    callback = supportsBinary;
    supportsBinary = false;
  }

  if ('function' == typeof utf8encode) {
    callback = utf8encode;
    utf8encode = null;
  }

  var data = (packet.data === undefined)
    ? undefined
    : packet.data.buffer || packet.data;

  if (global.ArrayBuffer && data instanceof ArrayBuffer) {
    return encodeArrayBuffer(packet, supportsBinary, callback);
  } else if (Blob && data instanceof global.Blob) {
    return encodeBlob(packet, supportsBinary, callback);
  }

  // might be an object with { base64: true, data: dataAsBase64String }
  if (data && data.base64) {
    return encodeBase64Object(packet, callback);
  }

  // Sending data as a utf-8 string
  var encoded = packets[packet.type];

  // data fragment is optional
  if (undefined !== packet.data) {
    encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data);
  }

  return callback('' + encoded);

};

function encodeBase64Object(packet, callback) {
  // packet data is an object { base64: true, data: dataAsBase64String }
  var message = 'b' + exports.packets[packet.type] + packet.data.data;
  return callback(message);
}

/**
 * Encode packet helpers for binary types
 */

function encodeArrayBuffer(packet, supportsBinary, callback) {
  if (!supportsBinary) {
    return exports.encodeBase64Packet(packet, callback);
  }

  var data = packet.data;
  var contentArray = new Uint8Array(data);
  var resultBuffer = new Uint8Array(1 + data.byteLength);

  resultBuffer[0] = packets[packet.type];
  for (var i = 0; i < contentArray.length; i++) {
    resultBuffer[i+1] = contentArray[i];
  }

  return callback(resultBuffer.buffer);
}

function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) {
  if (!supportsBinary) {
    return exports.encodeBase64Packet(packet, callback);
  }

  var fr = new FileReader();
  fr.onload = function() {
    packet.data = fr.result;
    exports.encodePacket(packet, supportsBinary, true, callback);
  };
  return fr.readAsArrayBuffer(packet.data);
}

function encodeBlob(packet, supportsBinary, callback) {
  if (!supportsBinary) {
    return exports.encodeBase64Packet(packet, callback);
  }

  if (dontSendBlobs) {
    return encodeBlobAsArrayBuffer(packet, supportsBinary, callback);
  }

  var length = new Uint8Array(1);
  length[0] = packets[packet.type];
  var blob = new Blob([length.buffer, packet.data]);

  return callback(blob);
}

/**
 * Encodes a packet with binary data in a base64 string
 *
 * @param {Object} packet, has `type` and `data`
 * @return {String} base64 encoded message
 */

exports.encodeBase64Packet = function(packet, callback) {
  var message = 'b' + exports.packets[packet.type];
  if (Blob && packet.data instanceof global.Blob) {
    var fr = new FileReader();
    fr.onload = function() {
      var b64 = fr.result.split(',')[1];
      callback(message + b64);
    };
    return fr.readAsDataURL(packet.data);
  }

  var b64data;
  try {
    b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data));
  } catch (e) {
    // iPhone Safari doesn't let you apply with typed arrays
    var typed = new Uint8Array(packet.data);
    var basic = new Array(typed.length);
    for (var i = 0; i < typed.length; i++) {
      basic[i] = typed[i];
    }
    b64data = String.fromCharCode.apply(null, basic);
  }
  message += global.btoa(b64data);
  return callback(message);
};

/**
 * Decodes a packet. Changes format to Blob if requested.
 *
 * @return {Object} with `type` and `data` (if any)
 * @api private
 */

exports.decodePacket = function (data, binaryType, utf8decode) {
  // String data
  if (typeof data == 'string' || data === undefined) {
    if (data.charAt(0) == 'b') {
      return exports.decodeBase64Packet(data.substr(1), binaryType);
    }

    if (utf8decode) {
      try {
        data = utf8.decode(data);
      } catch (e) {
        return err;
      }
    }
    var type = data.charAt(0);

    if (Number(type) != type || !packetslist[type]) {
      return err;
    }

    if (data.length > 1) {
      return { type: packetslist[type], data: data.substring(1) };
    } else {
      return { type: packetslist[type] };
    }
  }

  var asArray = new Uint8Array(data);
  var type = asArray[0];
  var rest = sliceBuffer(data, 1);
  if (Blob && binaryType === 'blob') {
    rest = new Blob([rest]);
  }
  return { type: packetslist[type], data: rest };
};

/**
 * Decodes a packet encoded in a base64 string
 *
 * @param {String} base64 encoded message
 * @return {Object} with `type` and `data` (if any)
 */

exports.decodeBase64Packet = function(msg, binaryType) {
  var type = packetslist[msg.charAt(0)];
  if (!global.ArrayBuffer) {
    return { type: type, data: { base64: true, data: msg.substr(1) } };
  }

  var data = base64encoder.decode(msg.substr(1));

  if (binaryType === 'blob' && Blob) {
    data = new Blob([data]);
  }

  return { type: type, data: data };
};

/**
 * Encodes multiple messages (payload).
 *
 *     <length>:data
 *
 * Example:
 *
 *     11:hello world2:hi
 *
 * If any contents are binary, they will be encoded as base64 strings. Base64
 * encoded strings are marked with a b before the length specifier
 *
 * @param {Array} packets
 * @api private
 */

exports.encodePayload = function (packets, supportsBinary, callback) {
  if (typeof supportsBinary == 'function') {
    callback = supportsBinary;
    supportsBinary = null;
  }

  var isBinary = hasBinary(packets);

  if (supportsBinary && isBinary) {
    if (Blob && !dontSendBlobs) {
      return exports.encodePayloadAsBlob(packets, callback);
    }

    return exports.encodePayloadAsArrayBuffer(packets, callback);
  }

  if (!packets.length) {
    return callback('0:');
  }

  function setLengthHeader(message) {
    return message.length + ':' + message;
  }

  function encodeOne(packet, doneCallback) {
    exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) {
      doneCallback(null, setLengthHeader(message));
    });
  }

  map(packets, encodeOne, function(err, results) {
    return callback(results.join(''));
  });
};

/**
 * Async array map using after
 */

function map(ary, each, done) {
  var result = new Array(ary.length);
  var next = after(ary.length, done);

  var eachWithIndex = function(i, el, cb) {
    each(el, function(error, msg) {
      result[i] = msg;
      cb(error, result);
    });
  };

  for (var i = 0; i < ary.length; i++) {
    eachWithIndex(i, ary[i], next);
  }
}

/*
 * Decodes data when a payload is maybe expected. Possible binary contents are
 * decoded from their base64 representation
 *
 * @param {String} data, callback method
 * @api public
 */

exports.decodePayload = function (data, binaryType, callback) {
  if (typeof data != 'string') {
    return exports.decodePayloadAsBinary(data, binaryType, callback);
  }

  if (typeof binaryType === 'function') {
    callback = binaryType;
    binaryType = null;
  }

  var packet;
  if (data == '') {
    // parser error - ignoring payload
    return callback(err, 0, 1);
  }

  var length = ''
    , n, msg;

  for (var i = 0, l = data.length; i < l; i++) {
    var chr = data.charAt(i);

    if (':' != chr) {
      length += chr;
    } else {
      if ('' == length || (length != (n = Number(length)))) {
        // parser error - ignoring payload
        return callback(err, 0, 1);
      }

      msg = data.substr(i + 1, n);

      if (length != msg.length) {
        // parser error - ignoring payload
        return callback(err, 0, 1);
      }

      if (msg.length) {
        packet = exports.decodePacket(msg, binaryType, true);

        if (err.type == packet.type && err.data == packet.data) {
          // parser error in individual packet - ignoring payload
          return callback(err, 0, 1);
        }

        var ret = callback(packet, i + n, l);
        if (false === ret) return;
      }

      // advance cursor
      i += n;
      length = '';
    }
  }

  if (length != '') {
    // parser error - ignoring payload
    return callback(err, 0, 1);
  }

};

/**
 * Encodes multiple messages (payload) as binary.
 *
 * <1 = binary, 0 = string><number from 0-9><number from 0-9>[...]<number
 * 255><data>
 *
 * Example:
 * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers
 *
 * @param {Array} packets
 * @return {ArrayBuffer} encoded payload
 * @api private
 */

exports.encodePayloadAsArrayBuffer = function(packets, callback) {
  if (!packets.length) {
    return callback(new ArrayBuffer(0));
  }

  function encodeOne(packet, doneCallback) {
    exports.encodePacket(packet, true, true, function(data) {
      return doneCallback(null, data);
    });
  }

  map(packets, encodeOne, function(err, encodedPackets) {
    var totalLength = encodedPackets.reduce(function(acc, p) {
      var len;
      if (typeof p === 'string'){
        len = p.length;
      } else {
        len = p.byteLength;
      }
      return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2
    }, 0);

    var resultArray = new Uint8Array(totalLength);

    var bufferIndex = 0;
    encodedPackets.forEach(function(p) {
      var isString = typeof p === 'string';
      var ab = p;
      if (isString) {
        var view = new Uint8Array(p.length);
        for (var i = 0; i < p.length; i++) {
          view[i] = p.charCodeAt(i);
        }
        ab = view.buffer;
      }

      if (isString) { // not true binary
        resultArray[bufferIndex++] = 0;
      } else { // true binary
        resultArray[bufferIndex++] = 1;
      }

      var lenStr = ab.byteLength.toString();
      for (var i = 0; i < lenStr.length; i++) {
        resultArray[bufferIndex++] = parseInt(lenStr[i]);
      }
      resultArray[bufferIndex++] = 255;

      var view = new Uint8Array(ab);
      for (var i = 0; i < view.length; i++) {
        resultArray[bufferIndex++] = view[i];
      }
    });

    return callback(resultArray.buffer);
  });
};

/**
 * Encode as Blob
 */

exports.encodePayloadAsBlob = function(packets, callback) {
  function encodeOne(packet, doneCallback) {
    exports.encodePacket(packet, true, true, function(encoded) {
      var binaryIdentifier = new Uint8Array(1);
      binaryIdentifier[0] = 1;
      if (typeof encoded === 'string') {
        var view = new Uint8Array(encoded.length);
        for (var i = 0; i < encoded.length; i++) {
          view[i] = encoded.charCodeAt(i);
        }
        encoded = view.buffer;
        binaryIdentifier[0] = 0;
      }

      var len = (encoded instanceof ArrayBuffer)
        ? encoded.byteLength
        : encoded.size;

      var lenStr = len.toString();
      var lengthAry = new Uint8Array(lenStr.length + 1);
      for (var i = 0; i < lenStr.length; i++) {
        lengthAry[i] = parseInt(lenStr[i]);
      }
      lengthAry[lenStr.length] = 255;

      if (Blob) {
        var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]);
        doneCallback(null, blob);
      }
    });
  }

  map(packets, encodeOne, function(err, results) {
    return callback(new Blob(results));
  });
};

/*
 * Decodes data when a payload is maybe expected. Strings are decoded by
 * interpreting each byte as a key code for entries marked to start with 0. See
 * description of encodePayloadAsBinary
 *
 * @param {ArrayBuffer} data, callback method
 * @api public
 */

exports.decodePayloadAsBinary = function (data, binaryType, callback) {
  if (typeof binaryType === 'function') {
    callback = binaryType;
    binaryType = null;
  }

  var bufferTail = data;
  var buffers = [];

  var numberTooLong = false;
  while (bufferTail.byteLength > 0) {
    var tailArray = new Uint8Array(bufferTail);
    var isString = tailArray[0] === 0;
    var msgLength = '';

    for (var i = 1; ; i++) {
      if (tailArray[i] == 255) break;

      if (msgLength.length > 310) {
        numberTooLong = true;
        break;
      }

      msgLength += tailArray[i];
    }

    if(numberTooLong) return callback(err, 0, 1);

    bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length);
    msgLength = parseInt(msgLength);

    var msg = sliceBuffer(bufferTail, 0, msgLength);
    if (isString) {
      try {
        msg = String.fromCharCode.apply(null, new Uint8Array(msg));
      } catch (e) {
        // iPhone Safari doesn't let you apply to typed arrays
        var typed = new Uint8Array(msg);
        msg = '';
        for (var i = 0; i < typed.length; i++) {
          msg += String.fromCharCode(typed[i]);
        }
      }
    }

    buffers.push(msg);
    bufferTail = sliceBuffer(bufferTail, msgLength);
  }

  var total = buffers.length;
  buffers.forEach(function(buffer, i) {
    callback(exports.decodePacket(buffer, binaryType, true), i, total);
  });
};

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"./keys":28,"after":6,"arraybuffer.slice":7,"base64-arraybuffer":9,"blob":10,"has-binary":29,"utf8":45}],28:[function(_dereq_,module,exports){

/**
 * Gets the keys for an object.
 *
 * @return {Array} keys
 * @api private
 */

module.exports = Object.keys || function keys (obj){
  var arr = [];
  var has = Object.prototype.hasOwnProperty;

  for (var i in obj) {
    if (has.call(obj, i)) {
      arr.push(i);
    }
  }
  return arr;
};

},{}],29:[function(_dereq_,module,exports){
(function (global){

/*
 * Module requirements.
 */

var isArray = _dereq_('isarray');

/**
 * Module exports.
 */

module.exports = hasBinary;

/**
 * Checks for binary data.
 *
 * Right now only Buffer and ArrayBuffer are supported..
 *
 * @param {Object} anything
 * @api public
 */

function hasBinary(data) {

  function _hasBinary(obj) {
    if (!obj) return false;

    if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
         (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
         (global.Blob && obj instanceof Blob) ||
         (global.File && obj instanceof File)
        ) {
      return true;
    }

    if (isArray(obj)) {
      for (var i = 0; i < obj.length; i++) {
          if (_hasBinary(obj[i])) {
              return true;
          }
      }
    } else if (obj && 'object' == typeof obj) {
      if (obj.toJSON) {
        obj = obj.toJSON();
      }

      for (var key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
          return true;
        }
      }
    }

    return false;
  }

  return _hasBinary(data);
}

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"isarray":34}],30:[function(_dereq_,module,exports){

/**
 * Returns `this`. Execute this without a "context" (i.e. without it being
 * attached to an object of the left-hand side), and `this` points to the
 * "global" scope of the current JS execution.
 */

module.exports = (function () { return this; })();

},{}],31:[function(_dereq_,module,exports){
(function (global){

/*
 * Module requirements.
 */

var isArray = _dereq_('isarray');

/**
 * Module exports.
 */

module.exports = hasBinary;

/**
 * Checks for binary data.
 *
 * Right now only Buffer and ArrayBuffer are supported..
 *
 * @param {Object} anything
 * @api public
 */

function hasBinary(data) {

  function _hasBinary(obj) {
    if (!obj) return false;

    if ( (global.Buffer && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) ||
         (global.ArrayBuffer && obj instanceof ArrayBuffer) ||
         (global.Blob && obj instanceof Blob) ||
         (global.File && obj instanceof File)
        ) {
      return true;
    }

    if (isArray(obj)) {
      for (var i = 0; i < obj.length; i++) {
          if (_hasBinary(obj[i])) {
              return true;
          }
      }
    } else if (obj && 'object' == typeof obj) {
      // see: https://github.com/Automattic/has-binary/pull/4
      if (obj.toJSON && 'function' == typeof obj.toJSON) {
        obj = obj.toJSON();
      }

      for (var key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
          return true;
        }
      }
    }

    return false;
  }

  return _hasBinary(data);
}

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"isarray":34}],32:[function(_dereq_,module,exports){

/**
 * Module dependencies.
 */

var global = _dereq_('global');

/**
 * Module exports.
 *
 * Logic borrowed from Modernizr:
 *
 *   - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
 */

try {
  module.exports = 'XMLHttpRequest' in global &&
    'withCredentials' in new global.XMLHttpRequest();
} catch (err) {
  // if XMLHttp support is disabled in IE then it will throw
  // when trying to create
  module.exports = false;
}

},{"global":30}],33:[function(_dereq_,module,exports){

var indexOf = [].indexOf;

module.exports = function(arr, obj){
  if (indexOf) return arr.indexOf(obj);
  for (var i = 0; i < arr.length; ++i) {
    if (arr[i] === obj) return i;
  }
  return -1;
};
},{}],34:[function(_dereq_,module,exports){
module.exports = Array.isArray || function (arr) {
  return Object.prototype.toString.call(arr) == '[object Array]';
};

},{}],35:[function(_dereq_,module,exports){
(function (global){
/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */
;(function () {
  // Detect the `define` function exposed by asynchronous module loaders. The
  // strict `define` check is necessary for compatibility with `r.js`.
  var isLoader = typeof define === "function" && define.amd;

  // A set of types used to distinguish objects from primitives.
  var objectTypes = {
    "function": true,
    "object": true
  };

  // Detect the `exports` object exposed by CommonJS implementations.
  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;

  // Use the `global` object exposed by Node (including Browserify via
  // `insert-module-globals`), Narwhal, and Ringo as the default context,
  // and the `window` object in browsers. Rhino exports a `global` function
  // instead.
  var root = objectTypes[typeof window] && window || this,
      freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global;

  if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) {
    root = freeGlobal;
  }

  // Public: Initializes JSON 3 using the given `context` object, attaching the
  // `stringify` and `parse` functions to the specified `exports` object.
  function runInContext(context, exports) {
    context || (context = root["Object"]());
    exports || (exports = root["Object"]());

    // Native constructor aliases.
    var Number = context["Number"] || root["Number"],
        String = context["String"] || root["String"],
        Object = context["Object"] || root["Object"],
        Date = context["Date"] || root["Date"],
        SyntaxError = context["SyntaxError"] || root["SyntaxError"],
        TypeError = context["TypeError"] || root["TypeError"],
        Math = context["Math"] || root["Math"],
        nativeJSON = context["JSON"] || root["JSON"];

    // Delegate to the native `stringify` and `parse` implementations.
    if (typeof nativeJSON == "object" && nativeJSON) {
      exports.stringify = nativeJSON.stringify;
      exports.parse = nativeJSON.parse;
    }

    // Convenience aliases.
    var objectProto = Object.prototype,
        getClass = objectProto.toString,
        isProperty, forEach, undef;

    // Test the `Date#getUTC*` methods. Based on work by @Yaffle.
    var isExtended = new Date(-3509827334573292);
    try {
      // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
      // results for certain dates in Opera >= 10.53.
      isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
        // Safari < 2.0.2 stores the internal millisecond time value correctly,
        // but clips the values returned by the date methods to the range of
        // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
        isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
    } catch (exception) {}

    // Internal: Determines whether the native `JSON.stringify` and `parse`
    // implementations are spec-compliant. Based on work by Ken Snyder.
    function has(name) {
      if (has[name] !== undef) {
        // Return cached feature test result.
        return has[name];
      }
      var isSupported;
      if (name == "bug-string-char-index") {
        // IE <= 7 doesn't support accessing string characters using square
        // bracket notation. IE 8 only supports this for primitives.
        isSupported = "a"[0] != "a";
      } else if (name == "json") {
        // Indicates whether both `JSON.stringify` and `JSON.parse` are
        // supported.
        isSupported = has("json-stringify") && has("json-parse");
      } else {
        var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';
        // Test `JSON.stringify`.
        if (name == "json-stringify") {
          var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended;
          if (stringifySupported) {
            // A test function object with a custom `toJSON` method.
            (value = function () {
              return 1;
            }).toJSON = value;
            try {
              stringifySupported =
                // Firefox 3.1b1 and b2 serialize string, number, and boolean
                // primitives as object literals.
                stringify(0) === "0" &&
                // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
                // literals.
                stringify(new Number()) === "0" &&
                stringify(new String()) == '""' &&
                // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
                // does not define a canonical JSON representation (this applies to
                // objects with `toJSON` properties as well, *unless* they are nested
                // within an object or array).
                stringify(getClass) === undef &&
                // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
                // FF 3.1b3 pass this test.
                stringify(undef) === undef &&
                // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
                // respectively, if the value is omitted entirely.
                stringify() === undef &&
                // FF 3.1b1, 2 throw an error if the given value is not a number,
                // string, array, object, Boolean, or `null` literal. This applies to
                // objects with custom `toJSON` methods as well, unless they are nested
                // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
                // methods entirely.
                stringify(value) === "1" &&
                stringify([value]) == "[1]" &&
                // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
                // `"[null]"`.
                stringify([undef]) == "[null]" &&
                // YUI 3.0.0b1 fails to serialize `null` literals.
                stringify(null) == "null" &&
                // FF 3.1b1, 2 halts serialization if an array contains a function:
                // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
                // elides non-JSON values from objects and arrays, unless they
                // define custom `toJSON` methods.
                stringify([undef, getClass, null]) == "[null,null,null]" &&
                // Simple serialization test. FF 3.1b1 uses Unicode escape sequences
                // where character escape codes are expected (e.g., `\b` => `\u0008`).
                stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
                // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
                stringify(null, value) === "1" &&
                stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
                // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
                // serialize extended years.
                stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
                // The milliseconds are optional in ES 5, but required in 5.1.
                stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
                // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
                // four-digit years instead of six-digit years. Credits: @Yaffle.
                stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
                // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
                // values less than 1000. Credits: @Yaffle.
                stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
            } catch (exception) {
              stringifySupported = false;
            }
          }
          isSupported = stringifySupported;
        }
        // Test `JSON.parse`.
        if (name == "json-parse") {
          var parse = exports.parse;
          if (typeof parse == "function") {
            try {
              // FF 3.1b1, b2 will throw an exception if a bare literal is provided.
              // Conforming implementations should also coerce the initial argument to
              // a string prior to parsing.
              if (parse("0") === 0 && !parse(false)) {
                // Simple parsing test.
                value = parse(serialized);
                var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
                if (parseSupported) {
                  try {
                    // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
                    parseSupported = !parse('"\t"');
                  } catch (exception) {}
                  if (parseSupported) {
                    try {
                      // FF 4.0 and 4.0.1 allow leading `+` signs and leading
                      // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
                      // certain octal literals.
                      parseSupported = parse("01") !== 1;
                    } catch (exception) {}
                  }
                  if (parseSupported) {
                    try {
                      // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
                      // points. These environments, along with FF 3.1b1 and 2,
                      // also allow trailing commas in JSON objects and arrays.
                      parseSupported = parse("1.") !== 1;
                    } catch (exception) {}
                  }
                }
              }
            } catch (exception) {
              parseSupported = false;
            }
          }
          isSupported = parseSupported;
        }
      }
      return has[name] = !!isSupported;
    }

    if (!has("json")) {
      // Common `[[Class]]` name aliases.
      var functionClass = "[object Function]",
          dateClass = "[object Date]",
          numberClass = "[object Number]",
          stringClass = "[object String]",
          arrayClass = "[object Array]",
          booleanClass = "[object Boolean]";

      // Detect incomplete support for accessing string characters by index.
      var charIndexBuggy = has("bug-string-char-index");

      // Define additional utility methods if the `Date` methods are buggy.
      if (!isExtended) {
        var floor = Math.floor;
        // A mapping between the months of the year and the number of days between
        // January 1st and the first of the respective month.
        var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
        // Internal: Calculates the number of days between the Unix epoch and the
        // first day of the given month.
        var getDay = function (year, month) {
          return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
        };
      }

      // Internal: Determines if a property is a direct property of the given
      // object. Delegates to the native `Object#hasOwnProperty` method.
      if (!(isProperty = objectProto.hasOwnProperty)) {
        isProperty = function (property) {
          var members = {}, constructor;
          if ((members.__proto__ = null, members.__proto__ = {
            // The *proto* property cannot be set multiple times in recent
            // versions of Firefox and SeaMonkey.
            "toString": 1
          }, members).toString != getClass) {
            // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
            // supports the mutable *proto* property.
            isProperty = function (property) {
              // Capture and break the object's prototype chain (see section 8.6.2
              // of the ES 5.1 spec). The parenthesized expression prevents an
              // unsafe transformation by the Closure Compiler.
              var original = this.__proto__, result = property in (this.__proto__ = null, this);
              // Restore the original prototype chain.
              this.__proto__ = original;
              return result;
            };
          } else {
            // Capture a reference to the top-level `Object` constructor.
            constructor = members.constructor;
            // Use the `constructor` property to simulate `Object#hasOwnProperty` in
            // other environments.
            isProperty = function (property) {
              var parent = (this.constructor || constructor).prototype;
              return property in this && !(property in parent && this[property] === parent[property]);
            };
          }
          members = null;
          return isProperty.call(this, property);
        };
      }

      // Internal: Normalizes the `for...in` iteration algorithm across
      // environments. Each enumerated key is yielded to a `callback` function.
      forEach = function (object, callback) {
        var size = 0, Properties, members, property;

        // Tests for bugs in the current environment's `for...in` algorithm. The
        // `valueOf` property inherits the non-enumerable flag from
        // `Object.prototype` in older versions of IE, Netscape, and Mozilla.
        (Properties = function () {
          this.valueOf = 0;
        }).prototype.valueOf = 0;

        // Iterate over a new instance of the `Properties` class.
        members = new Properties();
        for (property in members) {
          // Ignore all properties inherited from `Object.prototype`.
          if (isProperty.call(members, property)) {
            size++;
          }
        }
        Properties = members = null;

        // Normalize the iteration algorithm.
        if (!size) {
          // A list of non-enumerable properties inherited from `Object.prototype`.
          members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
          // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
          // properties.
          forEach = function (object, callback) {
            var isFunction = getClass.call(object) == functionClass, property, length;
            var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty;
            for (property in object) {
              // Gecko <= 1.0 enumerates the `prototype` property of functions under
              // certain conditions; IE does not.
              if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
                callback(property);
              }
            }
            // Manually invoke the callback for each non-enumerable property.
            for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
          };
        } else if (size == 2) {
          // Safari <= 2.0.4 enumerates shadowed properties twice.
          forEach = function (object, callback) {
            // Create a set of iterated properties.
            var members = {}, isFunction = getClass.call(object) == functionClass, property;
            for (property in object) {
              // Store each property name to prevent double enumeration. The
              // `prototype` property of functions is not enumerated due to cross-
              // environment inconsistencies.
              if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
                callback(property);
              }
            }
          };
        } else {
          // No bugs detected; use the standard `for...in` algorithm.
          forEach = function (object, callback) {
            var isFunction = getClass.call(object) == functionClass, property, isConstructor;
            for (property in object) {
              if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
                callback(property);
              }
            }
            // Manually invoke the callback for the `constructor` property due to
            // cross-environment inconsistencies.
            if (isConstructor || isProperty.call(object, (property = "constructor"))) {
              callback(property);
            }
          };
        }
        return forEach(object, callback);
      };

      // Public: Serializes a JavaScript `value` as a JSON string. The optional
      // `filter` argument may specify either a function that alters how object and
      // array members are serialized, or an array of strings and numbers that
      // indicates which properties should be serialized. The optional `width`
      // argument may be either a string or number that specifies the indentation
      // level of the output.
      if (!has("json-stringify")) {
        // Internal: A map of control characters and their escaped equivalents.
        var Escapes = {
          92: "\\\\",
          34: '\\"',
          8: "\\b",
          12: "\\f",
          10: "\\n",
          13: "\\r",
          9: "\\t"
        };

        // Internal: Converts `value` into a zero-padded string such that its
        // length is at least equal to `width`. The `width` must be <= 6.
        var leadingZeroes = "000000";
        var toPaddedString = function (width, value) {
          // The `|| 0` expression is necessary to work around a bug in
          // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
          return (leadingZeroes + (value || 0)).slice(-width);
        };

        // Internal: Double-quotes a string `value`, replacing all ASCII control
        // characters (characters with code unit values between 0 and 31) with
        // their escaped equivalents. This is an implementation of the
        // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
        var unicodePrefix = "\\u00";
        var quote = function (value) {
          var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10;
          var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value);
          for (; index < length; index++) {
            var charCode = value.charCodeAt(index);
            // If the character is a control character, append its Unicode or
            // shorthand escape sequence; otherwise, append the character as-is.
            switch (charCode) {
              case 8: case 9: case 10: case 12: case 13: case 34: case 92:
                result += Escapes[charCode];
                break;
              default:
                if (charCode < 32) {
                  result += unicodePrefix + toPaddedString(2, charCode.toString(16));
                  break;
                }
                result += useCharIndex ? symbols[index] : value.charAt(index);
            }
          }
          return result + '"';
        };

        // Internal: Recursively serializes an object. Implements the
        // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
        var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
          var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
          try {
            // Necessary for host object support.
            value = object[property];
          } catch (exception) {}
          if (typeof value == "object" && value) {
            className = getClass.call(value);
            if (className == dateClass && !isProperty.call(value, "toJSON")) {
              if (value > -1 / 0 && value < 1 / 0) {
                // Dates are serialized according to the `Date#toJSON` method
                // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
                // for the ISO 8601 date time string format.
                if (getDay) {
                  // Manually compute the year, month, date, hours, minutes,
                  // seconds, and milliseconds if the `getUTC*` methods are
                  // buggy. Adapted from @Yaffle's `date-shim` project.
                  date = floor(value / 864e5);
                  for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
                  for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
                  date = 1 + date - getDay(year, month);
                  // The `time` value specifies the time within the day (see ES
                  // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
                  // to compute `A modulo B`, as the `%` operator does not
                  // correspond to the `modulo` operation for negative numbers.
                  time = (value % 864e5 + 864e5) % 864e5;
                  // The hours, minutes, seconds, and milliseconds are obtained by
                  // decomposing the time within the day. See section 15.9.1.10.
                  hours = floor(time / 36e5) % 24;
                  minutes = floor(time / 6e4) % 60;
                  seconds = floor(time / 1e3) % 60;
                  milliseconds = time % 1e3;
                } else {
                  year = value.getUTCFullYear();
                  month = value.getUTCMonth();
                  date = value.getUTCDate();
                  hours = value.getUTCHours();
                  minutes = value.getUTCMinutes();
                  seconds = value.getUTCSeconds();
                  milliseconds = value.getUTCMilliseconds();
                }
                // Serialize extended years correctly.
                value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
                  "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
                  // Months, dates, hours, minutes, and seconds should have two
                  // digits; milliseconds should have three.
                  "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
                  // Milliseconds are optional in ES 5.0, but required in 5.1.
                  "." + toPaddedString(3, milliseconds) + "Z";
              } else {
                value = null;
              }
            } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
              // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
              // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
              // ignores all `toJSON` methods on these objects unless they are
              // defined directly on an instance.
              value = value.toJSON(property);
            }
          }
          if (callback) {
            // If a replacement function was provided, call it to obtain the value
            // for serialization.
            value = callback.call(object, property, value);
          }
          if (value === null) {
            return "null";
          }
          className = getClass.call(value);
          if (className == booleanClass) {
            // Booleans are represented literally.
            return "" + value;
          } else if (className == numberClass) {
            // JSON numbers must be finite. `Infinity` and `NaN` are serialized as
            // `"null"`.
            return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
          } else if (className == stringClass) {
            // Strings are double-quoted and escaped.
            return quote("" + value);
          }
          // Recursively serialize objects and arrays.
          if (typeof value == "object") {
            // Check for cyclic structures. This is a linear search; performance
            // is inversely proportional to the number of unique nested objects.
            for (length = stack.length; length--;) {
              if (stack[length] === value) {
                // Cyclic structures cannot be serialized by `JSON.stringify`.
                throw TypeError();
              }
            }
            // Add the object to the stack of traversed objects.
            stack.push(value);
            results = [];
            // Save the current indentation level and indent one additional level.
            prefix = indentation;
            indentation += whitespace;
            if (className == arrayClass) {
              // Recursively serialize array elements.
              for (index = 0, length = value.length; index < length; index++) {
                element = serialize(index, value, callback, properties, whitespace, indentation, stack);
                results.push(element === undef ? "null" : element);
              }
              result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
            } else {
              // Recursively serialize object members. Members are selected from
              // either a user-specified list of property names, or the object
              // itself.
              forEach(properties || value, function (property) {
                var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
                if (element !== undef) {
                  // According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
                  // is not the empty string, let `member` {quote(property) + ":"}
                  // be the concatenation of `member` and the `space` character."
                  // The "`space` character" refers to the literal space
                  // character, not the `space` {width} argument provided to
                  // `JSON.stringify`.
                  results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
                }
              });
              result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
            }
            // Remove the object from the traversed object stack.
            stack.pop();
            return result;
          }
        };

        // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
        exports.stringify = function (source, filter, width) {
          var whitespace, callback, properties, className;
          if (objectTypes[typeof filter] && filter) {
            if ((className = getClass.call(filter)) == functionClass) {
              callback = filter;
            } else if (className == arrayClass) {
              // Convert the property names array into a makeshift set.
              properties = {};
              for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
            }
          }
          if (width) {
            if ((className = getClass.call(width)) == numberClass) {
              // Convert the `width` to an integer and create a string containing
              // `width` number of space characters.
              if ((width -= width % 1) > 0) {
                for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
              }
            } else if (className == stringClass) {
              whitespace = width.length <= 10 ? width : width.slice(0, 10);
            }
          }
          // Opera <= 7.54u2 discards the values associated with empty string keys
          // (`""`) only if they are used directly within an object member list
          // (e.g., `!("" in { "": 1})`).
          return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
        };
      }

      // Public: Parses a JSON source string.
      if (!has("json-parse")) {
        var fromCharCode = String.fromCharCode;

        // Internal: A map of escaped control characters and their unescaped
        // equivalents.
        var Unescapes = {
          92: "\\",
          34: '"',
          47: "/",
          98: "\b",
          116: "\t",
          110: "\n",
          102: "\f",
          114: "\r"
        };

        // Internal: Stores the parser state.
        var Index, Source;

        // Internal: Resets the parser state and throws a `SyntaxError`.
        var abort = function () {
          Index = Source = null;
          throw SyntaxError();
        };

        // Internal: Returns the next token, or `"$"` if the parser has reached
        // the end of the source string. A token may be a string, number, `null`
        // literal, or Boolean literal.
        var lex = function () {
          var source = Source, length = source.length, value, begin, position, isSigned, charCode;
          while (Index < length) {
            charCode = source.charCodeAt(Index);
            switch (charCode) {
              case 9: case 10: case 13: case 32:
                // Skip whitespace tokens, including tabs, carriage returns, line
                // feeds, and space characters.
                Index++;
                break;
              case 123: case 125: case 91: case 93: case 58: case 44:
                // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
                // the current position.
                value = charIndexBuggy ? source.charAt(Index) : source[Index];
                Index++;
                return value;
              case 34:
                // `"` delimits a JSON string; advance to the next character and
                // begin parsing the string. String tokens are prefixed with the
                // sentinel `@` character to distinguish them from punctuators and
                // end-of-string tokens.
                for (value = "@", Index++; Index < length;) {
                  charCode = source.charCodeAt(Index);
                  if (charCode < 32) {
                    // Unescaped ASCII control characters (those with a code unit
                    // less than the space character) are not permitted.
                    abort();
                  } else if (charCode == 92) {
                    // A reverse solidus (`\`) marks the beginning of an escaped
                    // control character (including `"`, `\`, and `/`) or Unicode
                    // escape sequence.
                    charCode = source.charCodeAt(++Index);
                    switch (charCode) {
                      case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
                        // Revive escaped control characters.
                        value += Unescapes[charCode];
                        Index++;
                        break;
                      case 117:
                        // `\u` marks the beginning of a Unicode escape sequence.
                        // Advance to the first character and validate the
                        // four-digit code point.
                        begin = ++Index;
                        for (position = Index + 4; Index < position; Index++) {
                          charCode = source.charCodeAt(Index);
                          // A valid sequence comprises four hexdigits (case-
                          // insensitive) that form a single hexadecimal value.
                          if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
                            // Invalid Unicode escape sequence.
                            abort();
                          }
                        }
                        // Revive the escaped character.
                        value += fromCharCode("0x" + source.slice(begin, Index));
                        break;
                      default:
                        // Invalid escape sequence.
                        abort();
                    }
                  } else {
                    if (charCode == 34) {
                      // An unescaped double-quote character marks the end of the
                      // string.
                      break;
                    }
                    charCode = source.charCodeAt(Index);
                    begin = Index;
                    // Optimize for the common case where a string is valid.
                    while (charCode >= 32 && charCode != 92 && charCode != 34) {
                      charCode = source.charCodeAt(++Index);
                    }
                    // Append the string as-is.
                    value += source.slice(begin, Index);
                  }
                }
                if (source.charCodeAt(Index) == 34) {
                  // Advance to the next character and return the revived string.
                  Index++;
                  return value;
                }
                // Unterminated string.
                abort();
              default:
                // Parse numbers and literals.
                begin = Index;
                // Advance past the negative sign, if one is specified.
                if (charCode == 45) {
                  isSigned = true;
                  charCode = source.charCodeAt(++Index);
                }
                // Parse an integer or floating-point value.
                if (charCode >= 48 && charCode <= 57) {
                  // Leading zeroes are interpreted as octal literals.
                  if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
                    // Illegal octal literal.
                    abort();
                  }
                  isSigned = false;
                  // Parse the integer component.
                  for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
                  // Floats cannot contain a leading decimal point; however, this
                  // case is already accounted for by the parser.
                  if (source.charCodeAt(Index) == 46) {
                    position = ++Index;
                    // Parse the decimal component.
                    for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
                    if (position == Index) {
                      // Illegal trailing decimal.
                      abort();
                    }
                    Index = position;
                  }
                  // Parse exponents. The `e` denoting the exponent is
                  // case-insensitive.
                  charCode = source.charCodeAt(Index);
                  if (charCode == 101 || charCode == 69) {
                    charCode = source.charCodeAt(++Index);
                    // Skip past the sign following the exponent, if one is
                    // specified.
                    if (charCode == 43 || charCode == 45) {
                      Index++;
                    }
                    // Parse the exponential component.
                    for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
                    if (position == Index) {
                      // Illegal empty exponent.
                      abort();
                    }
                    Index = position;
                  }
                  // Coerce the parsed value to a JavaScript number.
                  return +source.slice(begin, Index);
                }
                // A negative sign may only precede numbers.
                if (isSigned) {
                  abort();
                }
                // `true`, `false`, and `null` literals.
                if (source.slice(Index, Index + 4) == "true") {
                  Index += 4;
                  return true;
                } else if (source.slice(Index, Index + 5) == "false") {
                  Index += 5;
                  return false;
                } else if (source.slice(Index, Index + 4) == "null") {
                  Index += 4;
                  return null;
                }
                // Unrecognized token.
                abort();
            }
          }
          // Return the sentinel `$` character if the parser has reached the end
          // of the source string.
          return "$";
        };

        // Internal: Parses a JSON `value` token.
        var get = function (value) {
          var results, hasMembers;
          if (value == "$") {
            // Unexpected end of input.
            abort();
          }
          if (typeof value == "string") {
            if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
              // Remove the sentinel `@` character.
              return value.slice(1);
            }
            // Parse object and array literals.
            if (value == "[") {
              // Parses a JSON array, returning a new JavaScript array.
              results = [];
              for (;; hasMembers || (hasMembers = true)) {
                value = lex();
                // A closing square bracket marks the end of the array literal.
                if (value == "]") {
                  break;
                }
                // If the array literal contains elements, the current token
                // should be a comma separating the previous element from the
                // next.
                if (hasMembers) {
                  if (value == ",") {
                    value = lex();
                    if (value == "]") {
                      // Unexpected trailing `,` in array literal.
                      abort();
                    }
                  } else {
                    // A `,` must separate each array element.
                    abort();
                  }
                }
                // Elisions and leading commas are not permitted.
                if (value == ",") {
                  abort();
                }
                results.push(get(value));
              }
              return results;
            } else if (value == "{") {
              // Parses a JSON object, returning a new JavaScript object.
              results = {};
              for (;; hasMembers || (hasMembers = true)) {
                value = lex();
                // A closing curly brace marks the end of the object literal.
                if (value == "}") {
                  break;
                }
                // If the object literal contains members, the current token
                // should be a comma separator.
                if (hasMembers) {
                  if (value == ",") {
                    value = lex();
                    if (value == "}") {
                      // Unexpected trailing `,` in object literal.
                      abort();
                    }
                  } else {
                    // A `,` must separate each object member.
                    abort();
                  }
                }
                // Leading commas are not permitted, object property names must be
                // double-quoted strings, and a `:` must separate each property
                // name and value.
                if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
                  abort();
                }
                results[value.slice(1)] = get(lex());
              }
              return results;
            }
            // Unexpected token encountered.
            abort();
          }
          return value;
        };

        // Internal: Updates a traversed object member.
        var update = function (source, property, callback) {
          var element = walk(source, property, callback);
          if (element === undef) {
            delete source[property];
          } else {
            source[property] = element;
          }
        };

        // Internal: Recursively traverses a parsed JSON object, invoking the
        // `callback` function for each value. This is an implementation of the
        // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
        var walk = function (source, property, callback) {
          var value = source[property], length;
          if (typeof value == "object" && value) {
            // `forEach` can't be used to traverse an array in Opera <= 8.54
            // because its `Object#hasOwnProperty` implementation returns `false`
            // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
            if (getClass.call(value) == arrayClass) {
              for (length = value.length; length--;) {
                update(value, length, callback);
              }
            } else {
              forEach(value, function (property) {
                update(value, property, callback);
              });
            }
          }
          return callback.call(source, property, value);
        };

        // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
        exports.parse = function (source, callback) {
          var result, value;
          Index = 0;
          Source = "" + source;
          result = get(lex());
          // If a JSON string contains multiple tokens, it is invalid.
          if (lex() != "$") {
            abort();
          }
          // Reset the parser state.
          Index = Source = null;
          return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
        };
      }
    }

    exports["runInContext"] = runInContext;
    return exports;
  }

  if (freeExports && !isLoader) {
    // Export for CommonJS environments.
    runInContext(root, freeExports);
  } else {
    // Export for web browsers and JavaScript engines.
    var nativeJSON = root.JSON,
        previousJSON = root["JSON3"],
        isRestored = false;

    var JSON3 = runInContext(root, (root["JSON3"] = {
      // Public: Restores the original value of the global `JSON` object and
      // returns a reference to the `JSON3` object.
      "noConflict": function () {
        if (!isRestored) {
          isRestored = true;
          root.JSON = nativeJSON;
          root["JSON3"] = previousJSON;
          nativeJSON = previousJSON = null;
        }
        return JSON3;
      }
    }));

    root.JSON = {
      "parse": JSON3.parse,
      "stringify": JSON3.stringify
    };
  }

  // Export for asynchronous module loaders.
  if (isLoader) {
    define(function () {
      return JSON3;
    });
  }
}).call(this);

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{}],36:[function(_dereq_,module,exports){
/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} options
 * @return {String|Number}
 * @api public
 */

module.exports = function(val, options){
  options = options || {};
  if ('string' == typeof val) return parse(val);
  return options.long
    ? long(val)
    : short(val);
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  str = '' + str;
  if (str.length > 10000) return;
  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
  if (!match) return;
  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();
  switch (type) {
    case 'years':
    case 'year':
    case 'yrs':
    case 'yr':
    case 'y':
      return n * y;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'hrs':
    case 'hr':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'mins':
    case 'min':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 'secs':
    case 'sec':
    case 's':
      return n * s;
    case 'milliseconds':
    case 'millisecond':
    case 'msecs':
    case 'msec':
    case 'ms':
      return n;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function short(ms) {
  if (ms >= d) return Math.round(ms / d) + 'd';
  if (ms >= h) return Math.round(ms / h) + 'h';
  if (ms >= m) return Math.round(ms / m) + 'm';
  if (ms >= s) return Math.round(ms / s) + 's';
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function long(ms) {
  return plural(ms, d, 'day')
    || plural(ms, h, 'hour')
    || plural(ms, m, 'minute')
    || plural(ms, s, 'second')
    || ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, n, name) {
  if (ms < n) return;
  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
  return Math.ceil(ms / n) + ' ' + name + 's';
}

},{}],37:[function(_dereq_,module,exports){
(function (global){
/**
 * JSON parse.
 *
 * @see Based on jQuery#parseJSON (MIT) and JSON2
 * @api private
 */

var rvalidchars = /^[\],:{}\s]*$/;
var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
var rtrimLeft = /^\s+/;
var rtrimRight = /\s+$/;

module.exports = function parsejson(data) {
  if ('string' != typeof data || !data) {
    return null;
  }

  data = data.replace(rtrimLeft, '').replace(rtrimRight, '');

  // Attempt to parse using the native JSON parser first
  if (global.JSON && JSON.parse) {
    return JSON.parse(data);
  }

  if (rvalidchars.test(data.replace(rvalidescape, '@')
      .replace(rvalidtokens, ']')
      .replace(rvalidbraces, ''))) {
    return (new Function('return ' + data))();
  }
};
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{}],38:[function(_dereq_,module,exports){
/**
 * Compiles a querystring
 * Returns string representation of the object
 *
 * @param {Object}
 * @api private
 */

exports.encode = function (obj) {
  var str = '';

  for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
      if (str.length) str += '&';
      str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]);
    }
  }

  return str;
};

/**
 * Parses a simple querystring into an object
 *
 * @param {String} qs
 * @api private
 */

exports.decode = function(qs){
  var qry = {};
  var pairs = qs.split('&');
  for (var i = 0, l = pairs.length; i < l; i++) {
    var pair = pairs[i].split('=');
    qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
  }
  return qry;
};

},{}],39:[function(_dereq_,module,exports){
/**
 * Parses an URI
 *
 * @author Steven Levithan <stevenlevithan.com> (MIT license)
 * @api private
 */

var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;

var parts = [
    'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
];

module.exports = function parseuri(str) {
    var src = str,
        b = str.indexOf('['),
        e = str.indexOf(']');

    if (b != -1 && e != -1) {
        str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length);
    }

    var m = re.exec(str || ''),
        uri = {},
        i = 14;

    while (i--) {
        uri[parts[i]] = m[i] || '';
    }

    if (b != -1 && e != -1) {
        uri.source = src;
        uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':');
        uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':');
        uri.ipv6uri = true;
    }

    return uri;
};

},{}],40:[function(_dereq_,module,exports){
(function (global){
/*global Blob,File*/

/**
 * Module requirements
 */

var isArray = _dereq_('isarray');
var isBuf = _dereq_('./is-buffer');

/**
 * Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
 * Anything with blobs or files should be fed through removeBlobs before coming
 * here.
 *
 * @param {Object} packet - socket.io event packet
 * @return {Object} with deconstructed packet and list of buffers
 * @api public
 */

exports.deconstructPacket = function(packet){
  var buffers = [];
  var packetData = packet.data;

  function _deconstructPacket(data) {
    if (!data) return data;

    if (isBuf(data)) {
      var placeholder = { _placeholder: true, num: buffers.length };
      buffers.push(data);
      return placeholder;
    } else if (isArray(data)) {
      var newData = new Array(data.length);
      for (var i = 0; i < data.length; i++) {
        newData[i] = _deconstructPacket(data[i]);
      }
      return newData;
    } else if ('object' == typeof data && !(data instanceof Date)) {
      var newData = {};
      for (var key in data) {
        newData[key] = _deconstructPacket(data[key]);
      }
      return newData;
    }
    return data;
  }

  var pack = packet;
  pack.data = _deconstructPacket(packetData);
  pack.attachments = buffers.length; // number of binary 'attachments'
  return {packet: pack, buffers: buffers};
};

/**
 * Reconstructs a binary packet from its placeholder packet and buffers
 *
 * @param {Object} packet - event packet with placeholders
 * @param {Array} buffers - binary buffers to put in placeholder positions
 * @return {Object} reconstructed packet
 * @api public
 */

exports.reconstructPacket = function(packet, buffers) {
  var curPlaceHolder = 0;

  function _reconstructPacket(data) {
    if (data && data._placeholder) {
      var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway)
      return buf;
    } else if (isArray(data)) {
      for (var i = 0; i < data.length; i++) {
        data[i] = _reconstructPacket(data[i]);
      }
      return data;
    } else if (data && 'object' == typeof data) {
      for (var key in data) {
        data[key] = _reconstructPacket(data[key]);
      }
      return data;
    }
    return data;
  }

  packet.data = _reconstructPacket(packet.data);
  packet.attachments = undefined; // no longer useful
  return packet;
};

/**
 * Asynchronously removes Blobs or Files from data via
 * FileReader's readAsArrayBuffer method. Used before encoding
 * data as msgpack. Calls callback with the blobless data.
 *
 * @param {Object} data
 * @param {Function} callback
 * @api private
 */

exports.removeBlobs = function(data, callback) {
  function _removeBlobs(obj, curKey, containingObject) {
    if (!obj) return obj;

    // convert any blob
    if ((global.Blob && obj instanceof Blob) ||
        (global.File && obj instanceof File)) {
      pendingBlobs++;

      // async filereader
      var fileReader = new FileReader();
      fileReader.onload = function() { // this.result == arraybuffer
        if (containingObject) {
          containingObject[curKey] = this.result;
        }
        else {
          bloblessData = this.result;
        }

        // if nothing pending its callback time
        if(! --pendingBlobs) {
          callback(bloblessData);
        }
      };

      fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
    } else if (isArray(obj)) { // handle array
      for (var i = 0; i < obj.length; i++) {
        _removeBlobs(obj[i], i, obj);
      }
    } else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object
      for (var key in obj) {
        _removeBlobs(obj[key], key, obj);
      }
    }
  }

  var pendingBlobs = 0;
  var bloblessData = data;
  _removeBlobs(bloblessData);
  if (!pendingBlobs) {
    callback(bloblessData);
  }
};

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{"./is-buffer":42,"isarray":34}],41:[function(_dereq_,module,exports){

/**
 * Module dependencies.
 */

var debug = _dereq_('debug')('socket.io-parser');
var json = _dereq_('json3');
var isArray = _dereq_('isarray');
var Emitter = _dereq_('component-emitter');
var binary = _dereq_('./binary');
var isBuf = _dereq_('./is-buffer');

/**
 * Protocol version.
 *
 * @api public
 */

exports.protocol = 4;

/**
 * Packet types.
 *
 * @api public
 */

exports.types = [
  'CONNECT',
  'DISCONNECT',
  'EVENT',
  'BINARY_EVENT',
  'ACK',
  'BINARY_ACK',
  'ERROR'
];

/**
 * Packet type `connect`.
 *
 * @api public
 */

exports.CONNECT = 0;

/**
 * Packet type `disconnect`.
 *
 * @api public
 */

exports.DISCONNECT = 1;

/**
 * Packet type `event`.
 *
 * @api public
 */

exports.EVENT = 2;

/**
 * Packet type `ack`.
 *
 * @api public
 */

exports.ACK = 3;

/**
 * Packet type `error`.
 *
 * @api public
 */

exports.ERROR = 4;

/**
 * Packet type 'binary event'
 *
 * @api public
 */

exports.BINARY_EVENT = 5;

/**
 * Packet type `binary ack`. For acks with binary arguments.
 *
 * @api public
 */

exports.BINARY_ACK = 6;

/**
 * Encoder constructor.
 *
 * @api public
 */

exports.Encoder = Encoder;

/**
 * Decoder constructor.
 *
 * @api public
 */

exports.Decoder = Decoder;

/**
 * A socket.io Encoder instance
 *
 * @api public
 */

function Encoder() {}

/**
 * Encode a packet as a single string if non-binary, or as a
 * buffer sequence, depending on packet type.
 *
 * @param {Object} obj - packet object
 * @param {Function} callback - function to handle encodings (likely engine.write)
 * @return Calls callback with Array of encodings
 * @api public
 */

Encoder.prototype.encode = function(obj, callback){
  debug('encoding packet %j', obj);

  if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
    encodeAsBinary(obj, callback);
  }
  else {
    var encoding = encodeAsString(obj);
    callback([encoding]);
  }
};

/**
 * Encode packet as string.
 *
 * @param {Object} packet
 * @return {String} encoded
 * @api private
 */

function encodeAsString(obj) {
  var str = '';
  var nsp = false;

  // first is type
  str += obj.type;

  // attachments if we have them
  if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) {
    str += obj.attachments;
    str += '-';
  }

  // if we have a namespace other than `/`
  // we append it followed by a comma `,`
  if (obj.nsp && '/' != obj.nsp) {
    nsp = true;
    str += obj.nsp;
  }

  // immediately followed by the id
  if (null != obj.id) {
    if (nsp) {
      str += ',';
      nsp = false;
    }
    str += obj.id;
  }

  // json data
  if (null != obj.data) {
    if (nsp) str += ',';
    str += json.stringify(obj.data);
  }

  debug('encoded %j as %s', obj, str);
  return str;
}

/**
 * Encode packet as 'buffer sequence' by removing blobs, and
 * deconstructing packet into object with placeholders and
 * a list of buffers.
 *
 * @param {Object} packet
 * @return {Buffer} encoded
 * @api private
 */

function encodeAsBinary(obj, callback) {

  function writeEncoding(bloblessData) {
    var deconstruction = binary.deconstructPacket(bloblessData);
    var pack = encodeAsString(deconstruction.packet);
    var buffers = deconstruction.buffers;

    buffers.unshift(pack); // add packet info to beginning of data list
    callback(buffers); // write all the buffers
  }

  binary.removeBlobs(obj, writeEncoding);
}

/**
 * A socket.io Decoder instance
 *
 * @return {Object} decoder
 * @api public
 */

function Decoder() {
  this.reconstructor = null;
}

/**
 * Mix in `Emitter` with Decoder.
 */

Emitter(Decoder.prototype);

/**
 * Decodes an ecoded packet string into packet JSON.
 *
 * @param {String} obj - encoded packet
 * @return {Object} packet
 * @api public
 */

Decoder.prototype.add = function(obj) {
  var packet;
  if ('string' == typeof obj) {
    packet = decodeString(obj);
    if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json
      this.reconstructor = new BinaryReconstructor(packet);

      // no attachments, labeled binary but no binary data to follow
      if (this.reconstructor.reconPack.attachments === 0) {
        this.emit('decoded', packet);
      }
    } else { // non-binary full packet
      this.emit('decoded', packet);
    }
  }
  else if (isBuf(obj) || obj.base64) { // raw binary data
    if (!this.reconstructor) {
      throw new Error('got binary data when not reconstructing a packet');
    } else {
      packet = this.reconstructor.takeBinaryData(obj);
      if (packet) { // received final buffer
        this.reconstructor = null;
        this.emit('decoded', packet);
      }
    }
  }
  else {
    throw new Error('Unknown type: ' + obj);
  }
};

/**
 * Decode a packet String (JSON data)
 *
 * @param {String} str
 * @return {Object} packet
 * @api private
 */

function decodeString(str) {
  var p = {};
  var i = 0;

  // look up type
  p.type = Number(str.charAt(0));
  if (null == exports.types[p.type]) return error();

  // look up attachments if type binary
  if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) {
    var buf = '';
    while (str.charAt(++i) != '-') {
      buf += str.charAt(i);
      if (i == str.length) break;
    }
    if (buf != Number(buf) || str.charAt(i) != '-') {
      throw new Error('Illegal attachments');
    }
    p.attachments = Number(buf);
  }

  // look up namespace (if any)
  if ('/' == str.charAt(i + 1)) {
    p.nsp = '';
    while (++i) {
      var c = str.charAt(i);
      if (',' == c) break;
      p.nsp += c;
      if (i == str.length) break;
    }
  } else {
    p.nsp = '/';
  }

  // look up id
  var next = str.charAt(i + 1);
  if ('' !== next && Number(next) == next) {
    p.id = '';
    while (++i) {
      var c = str.charAt(i);
      if (null == c || Number(c) != c) {
        --i;
        break;
      }
      p.id += str.charAt(i);
      if (i == str.length) break;
    }
    p.id = Number(p.id);
  }

  // look up json data
  if (str.charAt(++i)) {
    try {
      p.data = json.parse(str.substr(i));
    } catch(e){
      return error();
    }
  }

  debug('decoded %s as %j', str, p);
  return p;
}

/**
 * Deallocates a parser's resources
 *
 * @api public
 */

Decoder.prototype.destroy = function() {
  if (this.reconstructor) {
    this.reconstructor.finishedReconstruction();
  }
};

/**
 * A manager of a binary event's 'buffer sequence'. Should
 * be constructed whenever a packet of type BINARY_EVENT is
 * decoded.
 *
 * @param {Object} packet
 * @return {BinaryReconstructor} initialized reconstructor
 * @api private
 */

function BinaryReconstructor(packet) {
  this.reconPack = packet;
  this.buffers = [];
}

/**
 * Method to be called when binary data received from connection
 * after a BINARY_EVENT packet.
 *
 * @param {Buffer | ArrayBuffer} binData - the raw binary data received
 * @return {null | Object} returns null if more binary data is expected or
 *   a reconstructed packet object if all buffers have been received.
 * @api private
 */

BinaryReconstructor.prototype.takeBinaryData = function(binData) {
  this.buffers.push(binData);
  if (this.buffers.length == this.reconPack.attachments) { // done with buffer list
    var packet = binary.reconstructPacket(this.reconPack, this.buffers);
    this.finishedReconstruction();
    return packet;
  }
  return null;
};

/**
 * Cleans up binary packet reconstruction variables.
 *
 * @api private
 */

BinaryReconstructor.prototype.finishedReconstruction = function() {
  this.reconPack = null;
  this.buffers = [];
};

function error(data){
  return {
    type: exports.ERROR,
    data: 'parser error'
  };
}

},{"./binary":40,"./is-buffer":42,"component-emitter":43,"debug":14,"isarray":34,"json3":35}],42:[function(_dereq_,module,exports){
(function (global){

module.exports = isBuf;

/**
 * Returns true if obj is a buffer or an arraybuffer.
 *
 * @api private
 */

function isBuf(obj) {
  return (global.Buffer && global.Buffer.isBuffer(obj)) ||
         (global.ArrayBuffer && obj instanceof ArrayBuffer);
}

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{}],43:[function(_dereq_,module,exports){
arguments[4][26][0].apply(exports,arguments)
},{"dup":26}],44:[function(_dereq_,module,exports){
module.exports = toArray

function toArray(list, index) {
    var array = []

    index = index || 0

    for (var i = index || 0; i < list.length; i++) {
        array[i - index] = list[i]
    }

    return array
}

},{}],45:[function(_dereq_,module,exports){
(function (global){
/*! https://mths.be/utf8js v2.0.0 by @mathias */
;(function(root) {

    // Detect free variables `exports`
    var freeExports = typeof exports == 'object' && exports;

    // Detect free variable `module`
    var freeModule = typeof module == 'object' && module &&
        module.exports == freeExports && module;

    // Detect free variable `global`, from Node.js or Browserified code,
    // and use it as `root`
    var freeGlobal = typeof global == 'object' && global;
    if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
        root = freeGlobal;
    }

    /*--------------------------------------------------------------------------*/

    var stringFromCharCode = String.fromCharCode;

    // Taken from https://mths.be/punycode
    function ucs2decode(string) {
        var output = [];
        var counter = 0;
        var length = string.length;
        var value;
        var extra;
        while (counter < length) {
            value = string.charCodeAt(counter++);
            if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
                // high surrogate, and there is a next character
                extra = string.charCodeAt(counter++);
                if ((extra & 0xFC00) == 0xDC00) { // low surrogate
                    output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
                } else {
                    // unmatched surrogate; only append this code unit, in case the next
                    // code unit is the high surrogate of a surrogate pair
                    output.push(value);
                    counter--;
                }
            } else {
                output.push(value);
            }
        }
        return output;
    }

    // Taken from https://mths.be/punycode
    function ucs2encode(array) {
        var length = array.length;
        var index = -1;
        var value;
        var output = '';
        while (++index < length) {
            value = array[index];
            if (value > 0xFFFF) {
                value -= 0x10000;
                output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
                value = 0xDC00 | value & 0x3FF;
            }
            output += stringFromCharCode(value);
        }
        return output;
    }

    function checkScalarValue(codePoint) {
        if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
            throw Error(
                'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
                ' is not a scalar value'
            );
        }
    }
    /*--------------------------------------------------------------------------*/

    function createByte(codePoint, shift) {
        return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
    }

    function encodeCodePoint(codePoint) {
        if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
            return stringFromCharCode(codePoint);
        }
        var symbol = '';
        if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
            symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
        }
        else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
            checkScalarValue(codePoint);
            symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
            symbol += createByte(codePoint, 6);
        }
        else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
            symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
            symbol += createByte(codePoint, 12);
            symbol += createByte(codePoint, 6);
        }
        symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
        return symbol;
    }

    function utf8encode(string) {
        var codePoints = ucs2decode(string);
        var length = codePoints.length;
        var index = -1;
        var codePoint;
        var byteString = '';
        while (++index < length) {
            codePoint = codePoints[index];
            byteString += encodeCodePoint(codePoint);
        }
        return byteString;
    }

    /*--------------------------------------------------------------------------*/

    function readContinuationByte() {
        if (byteIndex >= byteCount) {
            throw Error('Invalid byte index');
        }

        var continuationByte = byteArray[byteIndex] & 0xFF;
        byteIndex++;

        if ((continuationByte & 0xC0) == 0x80) {
            return continuationByte & 0x3F;
        }

        // If we end up here, it’s not a continuation byte
        throw Error('Invalid continuation byte');
    }

    function decodeSymbol() {
        var byte1;
        var byte2;
        var byte3;
        var byte4;
        var codePoint;

        if (byteIndex > byteCount) {
            throw Error('Invalid byte index');
        }

        if (byteIndex == byteCount) {
            return false;
        }

        // Read first byte
        byte1 = byteArray[byteIndex] & 0xFF;
        byteIndex++;

        // 1-byte sequence (no continuation bytes)
        if ((byte1 & 0x80) == 0) {
            return byte1;
        }

        // 2-byte sequence
        if ((byte1 & 0xE0) == 0xC0) {
            var byte2 = readContinuationByte();
            codePoint = ((byte1 & 0x1F) << 6) | byte2;
            if (codePoint >= 0x80) {
                return codePoint;
            } else {
                throw Error('Invalid continuation byte');
            }
        }

        // 3-byte sequence (may include unpaired surrogates)
        if ((byte1 & 0xF0) == 0xE0) {
            byte2 = readContinuationByte();
            byte3 = readContinuationByte();
            codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
            if (codePoint >= 0x0800) {
                checkScalarValue(codePoint);
                return codePoint;
            } else {
                throw Error('Invalid continuation byte');
            }
        }

        // 4-byte sequence
        if ((byte1 & 0xF8) == 0xF0) {
            byte2 = readContinuationByte();
            byte3 = readContinuationByte();
            byte4 = readContinuationByte();
            codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
                (byte3 << 0x06) | byte4;
            if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
                return codePoint;
            }
        }

        throw Error('Invalid UTF-8 detected');
    }

    var byteArray;
    var byteCount;
    var byteIndex;
    function utf8decode(byteString) {
        byteArray = ucs2decode(byteString);
        byteCount = byteArray.length;
        byteIndex = 0;
        var codePoints = [];
        var tmp;
        while ((tmp = decodeSymbol()) !== false) {
            codePoints.push(tmp);
        }
        return ucs2encode(codePoints);
    }

    /*--------------------------------------------------------------------------*/

    var utf8 = {
        'version': '2.0.0',
        'encode': utf8encode,
        'decode': utf8decode
    };

    // Some AMD build optimizers, like r.js, check for specific condition patterns
    // like the following:
    if (
        typeof define == 'function' &&
        typeof define.amd == 'object' &&
        define.amd
    ) {
        define(function() {
            return utf8;
        });
    }   else if (freeExports && !freeExports.nodeType) {
        if (freeModule) { // in Node.js or RingoJS v0.8.0+
            freeModule.exports = utf8;
        } else { // in Narwhal or RingoJS v0.7.0-
            var object = {};
            var hasOwnProperty = object.hasOwnProperty;
            for (var key in utf8) {
                hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
            }
        }
    } else { // in Rhino or a web browser
        root.utf8 = utf8;
    }

}(this));

}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {})
},{}],46:[function(_dereq_,module,exports){
'use strict';

var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('')
  , length = 64
  , map = {}
  , seed = 0
  , i = 0
  , prev;

/**
 * Return a string representing the specified number.
 *
 * @param {Number} num The number to convert.
 * @returns {String} The string representation of the number.
 * @api public
 */
function encode(num) {
  var encoded = '';

  do {
    encoded = alphabet[num % length] + encoded;
    num = Math.floor(num / length);
  } while (num > 0);

  return encoded;
}

/**
 * Return the integer value specified by the given string.
 *
 * @param {String} str The string to convert.
 * @returns {Number} The integer value represented by the string.
 * @api public
 */
function decode(str) {
  var decoded = 0;

  for (i = 0; i < str.length; i++) {
    decoded = decoded * length + map[str.charAt(i)];
  }

  return decoded;
}

/**
 * Yeast: A tiny growing id generator.
 *
 * @returns {String} A unique id.
 * @api public
 */
function yeast() {
  var now = encode(+new Date());

  if (now !== prev) return seed = 0, prev = now;
  return now +'.'+ encode(seed++);
}

//
// Map each character to its index.
//
for (; i < length; i++) map[alphabet[i]] = i;

//
// Expose the `yeast`, `encode` and `decode` functions.
//
yeast.encode = encode;
yeast.decode = decode;
module.exports = yeast;

},{}]},{},[1])(1)
});

/*!common/widgets/passport/dep/socketio-java/moment.min.js*/
;// moment.js
// version : 1.6.2
// author : Tim Wood
// license : MIT
// momentjs.com
(function(a,b){function A(a,b){this._d=a,this._isUTC=!!b}function B(a){return a<0?Math.ceil(a):Math.floor(a)}function C(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=B(j/1e3),b.seconds=i%60,h+=B(i/60),b.minutes=h%60,g+=B(h/60),b.hours=g%24,f+=B(g/24),f+=e*7,b.days=f%30,d+=B(f/30),b.months=d%12,c+=B(d/12),b.years=c}function D(a,b){var c=a+"";while(c.length<b)c="0"+c;return c}function E(a,b,c){var d=b._milliseconds,e=b._days,f=b._months,g;d&&a._d.setTime(+a+d*c),e&&a.date(a.date()+e*c),f&&(g=a.date(),a.date(1).month(a.month()+f*c).date(Math.min(g,a.daysInMonth())))}function F(a){return Object.prototype.toString.call(a)==="[object Array]"}function G(b){return new a(b[0],b[1]||0,b[2]||1,b[3]||0,b[4]||0,b[5]||0,b[6]||0)}function H(b,d){function q(d){var l,r;switch(d){case"M":return e+1;case"Mo":return e+1+o(e+1);case"MM":return D(e+1,2);case"MMM":return c.monthsShort[e];case"MMMM":return c.months[e];case"D":return f;case"Do":return f+o(f);case"DD":return D(f,2);case"DDD":return l=new a(g,e,f),r=new a(g,0,1),~~((l-r)/864e5+1.5);case"DDDo":return l=q("DDD"),l+o(l);case"DDDD":return D(q("DDD"),3);case"d":return h;case"do":return h+o(h);case"ddd":return c.weekdaysShort[h];case"dddd":return c.weekdays[h];case"w":return l=new a(g,e,f-h+5),r=new a(l.getFullYear(),0,4),~~((l-r)/864e5/7+1.5);case"wo":return l=q("w"),l+o(l);case"ww":return D(q("w"),2);case"YY":return D(g%100,2);case"YYYY":return g;case"a":return p?p(i,j,!1):i>11?"pm":"am";case"A":return p?p(i,j,!0):i>11?"PM":"AM";case"H":return i;case"HH":return D(i,2);case"h":return i%12||12;case"hh":return D(i%12||12,2);case"m":return j;case"mm":return D(j,2);case"s":return k;case"ss":return D(k,2);case"S":return~~(m/100);case"SS":return D(~~(m/10),2);case"SSS":return D(m,3);case"Z":return(n<0?"-":"+")+D(~~(Math.abs(n)/60),2)+":"+D(~~(Math.abs(n)%60),2);case"ZZ":return(n<0?"-":"+")+D(~~(10*Math.abs(n)/6),4);case"L":case"LL":case"LLL":case"LLLL":case"LT":return H(b,c.longDateFormat[d]);default:return d.replace(/(^\[)|(\\)|\]$/g,"")}}var e=b.month(),f=b.date(),g=b.year(),h=b.day(),i=b.hours(),j=b.minutes(),k=b.seconds(),m=b.milliseconds(),n=-b.zone(),o=c.ordinal,p=c.meridiem;return d.replace(l,q)}function I(a){switch(a){case"DDDD":return p;case"YYYY":return q;case"S":case"SS":case"SSS":case"DDD":return o;case"MMM":case"MMMM":case"ddd":case"dddd":case"a":case"A":return r;case"Z":case"ZZ":return s;case"T":return t;case"MM":case"DD":case"dd":case"YY":case"HH":case"hh":case"mm":case"ss":case"M":case"D":case"d":case"H":case"h":case"m":case"s":return n;default:return new RegExp(a.replace("\\",""))}}function J(a,b,d,e){var f;switch(a){case"M":case"MM":d[1]=b==null?0:~~b-1;break;case"MMM":case"MMMM":for(f=0;f<12;f++)if(c.monthsParse[f].test(b)){d[1]=f;break}break;case"D":case"DD":case"DDD":case"DDDD":d[2]=~~b;break;case"YY":b=~~b,d[0]=b+(b>70?1900:2e3);break;case"YYYY":d[0]=~~Math.abs(b);break;case"a":case"A":e.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":d[3]=~~b;break;case"m":case"mm":d[4]=~~b;break;case"s":case"ss":d[5]=~~b;break;case"S":case"SS":case"SSS":d[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":e.isUTC=!0,f=(b+"").match(x),f&&f[1]&&(e.tzh=~~f[1]),f&&f[2]&&(e.tzm=~~f[2]),f&&f[0]==="+"&&(e.tzh=-e.tzh,e.tzm=-e.tzm)}}function K(b,c){var d=[0,0,1,0,0,0,0],e={tzh:0,tzm:0},f=c.match(l),g,h;for(g=0;g<f.length;g++)h=(I(f[g]).exec(b)||[])[0],b=b.replace(I(f[g]),""),J(f[g],h,d,e);return e.isPm&&d[3]<12&&(d[3]+=12),e.isPm===!1&&d[3]===12&&(d[3]=0),d[3]+=e.tzh,d[4]+=e.tzm,e.isUTC?new a(a.UTC.apply({},d)):G(d)}function L(a,b){var c=Math.min(a.length,b.length),d=Math.abs(a.length-b.length),e=0,f;for(f=0;f<c;f++)~~a[f]!==~~b[f]&&e++;return e+d}function M(a,b){var c,d=a.match(m)||[],e,f=99,g,h,i;for(g=0;g<b.length;g++)h=K(a,b[g]),e=H(new A(h),b[g]).match(m)||[],i=L(d,e),i<f&&(f=i,c=h);return c}function N(b){var c="YYYY-MM-DDT",d;if(u.exec(b)){for(d=0;d<4;d++)if(w[d][1].exec(b)){c+=w[d][0];break}return s.exec(b)?K(b,c+" Z"):K(b,c)}return new a(b)}function O(a,b,d,e){var f=c.relativeTime[a];return typeof f=="function"?f(b||1,!!d,a,e):f.replace(/%d/i,b||1)}function P(a,b){var c=e(Math.abs(a)/1e3),d=e(c/60),f=e(d/60),g=e(f/24),h=e(g/365),i=c<45&&["s",c]||d===1&&["m"]||d<45&&["mm",d]||f===1&&["h"]||f<22&&["hh",f]||g===1&&["d"]||g<=25&&["dd",g]||g<=45&&["M"]||g<345&&["MM",e(g/30)]||h===1&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,O.apply({},i)}function Q(a,b){c.fn[a]=function(a){var c=this._isUTC?"UTC":"";return a!=null?(this._d["set"+c+b](a),this):this._d["get"+c+b]()}}function R(a){c.duration.fn[a]=function(){return this._data[a]}}function S(a,b){c.duration.fn["as"+a]=function(){return+this/b}}var c,d="1.6.2",e=Math.round,f,g={},h="en",i=typeof module!="undefined",j="months|monthsShort|monthsParse|weekdays|weekdaysShort|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),k=/^\/?Date\((\-?\d+)/i,l=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6};c=function(d,e){if(d===null||d==="")return null;var f,g,h;return c.isMoment(d)?(f=new a(+d._d),h=d._isUTC):e?F(e)?f=M(d,e):f=K(d,e):(g=k.exec(d),f=d===b?new a:g?new a(+g[1]):d instanceof a?d:F(d)?G(d):typeof d=="string"?N(d):new a(d)),new A(f,h)},c.utc=function(b,d){return F(b)?new A(new a(a.UTC.apply({},b)),!0):d&&b?c(b+" +0000",d+" Z").utc():c(b&&!s.exec(b)?b+"+0000":b).utc()},c.unix=function(a){return c(a*1e3)},c.duration=function(a,b){var d=c.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a;return e&&(b?f[b]=a:f.milliseconds=a),new C(f)},c.humanizeDuration=function(a,b,d){return c.duration(a,b===!0?null:b).humanize(b===!0?!0:d)},c.version=d,c.defaultFormat=v,c.lang=function(a,b){var d,e,f=[];if(!a)return h;if(b){for(d=0;d<12;d++)f[d]=new RegExp("^"+b.months[d]+"|^"+b.monthsShort[d].replace(".",""),"i");b.monthsParse=b.monthsParse||f,g[a]=b}if(g[a]){for(d=0;d<j.length;d++)c[j[d]]=g[a][j[d]]||g.en[j[d]];h=a}else i&&(e=require("./lang/"+a),c.lang(a,e))},c.lang("en",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},meridiem:!1,calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),c.isMoment=function(a){return a instanceof A},c.isDuration=function(a){return a instanceof C},c.fn=A.prototype={clone:function(){return c(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return H(this,a?a:c.defaultFormat)},add:function(a,b){var d=b?c.duration(+b,a):c.duration(a);return E(this,d,1),this},subtract:function(a,b){var d=b?c.duration(+b,a):c.duration(a);return E(this,d,-1),this},diff:function(a,b,d){var f=this._isUTC?c(a).utc():c(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return b==="months"?l=i*12+j+k/30:b==="years"?l=i+(j+k/30)/12:l=b==="seconds"?h/1e3:b==="minutes"?h/6e4:b==="hours"?h/36e5:b==="days"?h/864e5:b==="weeks"?h/6048e5:h,d?l:e(l)},from:function(a,b){return c.duration(this.diff(a)).humanize(!b)},fromNow:function(a){return this.from(c(),a)},calendar:function(){var a=this.diff(c().sod(),"days",!0),b=c.calendar,d=b.sameElse,e=a<-6?d:a<-1?b.lastWeek:a<0?b.lastDay:a<1?b.sameDay:a<2?b.nextDay:a<7?b.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone()<c([this.year()]).zone()||this.zone()<c([this.year(),5]).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return a==null?b:this.add({d:a-b})},sod:function(){return c(this).hours(0).minutes(0).seconds(0).milliseconds(0)},eod:function(){return this.sod().add({d:1,ms:-1})},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return c(this).month(this.month()+1).date(0).date()}};for(f=0;f<y.length;f++)Q(y[f].toLowerCase(),y[f]);Q("year","FullYear"),c.duration.fn=C.prototype={weeks:function(){return B(this.days()/7)},valueOf:function(){return this._milliseconds+this._days*864e5+this._months*2592e6},humanize:function(a){var b=+this,d=c.relativeTime,e=P(b,!a);return a&&(e=(b<=0?d.past:d.future).replace(/%s/i,e)),e}};for(f in z)z.hasOwnProperty(f)&&(S(f,z[f]),R(f.toLowerCase()));S("Weeks",6048e5),i&&(module.exports=c),typeof window!="undefined"&&typeof ender=="undefined"&&(window.moment=c),typeof define=="function"&&define.amd&&define('common/widgets/passport/dep/socketio-java/moment.min',['require'],function(require){return c})})(Date);
/*!common/widgets/passport/dep/jquery.qrcode/jquery.qrcode.min.js*/
;define('common/widgets/passport/dep/jquery.qrcode/jquery.qrcode.min', ['require', 'exports', 'module'], function(require, exports, module) {

  (function(r){r.fn.qrcode=function(h){var s;function u(a){this.mode=s;this.data=a}function o(a,c){this.typeNumber=a;this.errorCorrectLevel=c;this.modules=null;this.moduleCount=0;this.dataCache=null;this.dataList=[]}function q(a,c){if(void 0==a.length)throw Error(a.length+"/"+c);for(var d=0;d<a.length&&0==a[d];)d++;this.num=Array(a.length-d+c);for(var b=0;b<a.length-d;b++)this.num[b]=a[b+d]}function p(a,c){this.totalCount=a;this.dataCount=c}function t(){this.buffer=[];this.length=0}u.prototype={getLength:function(){return this.data.length},
  write:function(a){for(var c=0;c<this.data.length;c++)a.put(this.data.charCodeAt(c),8)}};o.prototype={addData:function(a){this.dataList.push(new u(a));this.dataCache=null},isDark:function(a,c){if(0>a||this.moduleCount<=a||0>c||this.moduleCount<=c)throw Error(a+","+c);return this.modules[a][c]},getModuleCount:function(){return this.moduleCount},make:function(){if(1>this.typeNumber){for(var a=1,a=1;40>a;a++){for(var c=p.getRSBlocks(a,this.errorCorrectLevel),d=new t,b=0,e=0;e<c.length;e++)b+=c[e].dataCount;
  for(e=0;e<this.dataList.length;e++)c=this.dataList[e],d.put(c.mode,4),d.put(c.getLength(),j.getLengthInBits(c.mode,a)),c.write(d);if(d.getLengthInBits()<=8*b)break}this.typeNumber=a}this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17;this.modules=Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=Array(this.moduleCount);for(var b=0;b<this.moduleCount;b++)this.modules[d][b]=null}this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-
  7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(a,c);7<=this.typeNumber&&this.setupTypeNumber(a);null==this.dataCache&&(this.dataCache=o.createData(this.typeNumber,this.errorCorrectLevel,this.dataList));this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,c){for(var d=-1;7>=d;d++)if(!(-1>=a+d||this.moduleCount<=a+d))for(var b=-1;7>=b;b++)-1>=c+b||this.moduleCount<=c+b||(this.modules[a+d][c+b]=
  0<=d&&6>=d&&(0==b||6==b)||0<=b&&6>=b&&(0==d||6==d)||2<=d&&4>=d&&2<=b&&4>=b?!0:!1)},getBestMaskPattern:function(){for(var a=0,c=0,d=0;8>d;d++){this.makeImpl(!0,d);var b=j.getLostPoint(this);if(0==d||a>b)a=b,c=d}return c},createMovieClip:function(a,c,d){a=a.createEmptyMovieClip(c,d);this.make();for(c=0;c<this.modules.length;c++)for(var d=1*c,b=0;b<this.modules[c].length;b++){var e=1*b;this.modules[c][b]&&(a.beginFill(0,100),a.moveTo(e,d),a.lineTo(e+1,d),a.lineTo(e+1,d+1),a.lineTo(e,d+1),a.endFill())}return a},
  setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(a=8;a<this.moduleCount-8;a++)null==this.modules[6][a]&&(this.modules[6][a]=0==a%2)},setupPositionAdjustPattern:function(){for(var a=j.getPatternPosition(this.typeNumber),c=0;c<a.length;c++)for(var d=0;d<a.length;d++){var b=a[c],e=a[d];if(null==this.modules[b][e])for(var f=-2;2>=f;f++)for(var i=-2;2>=i;i++)this.modules[b+f][e+i]=-2==f||2==f||-2==i||2==i||0==f&&0==i?!0:!1}},setupTypeNumber:function(a){for(var c=
  j.getBCHTypeNumber(this.typeNumber),d=0;18>d;d++){var b=!a&&1==(c>>d&1);this.modules[Math.floor(d/3)][d%3+this.moduleCount-8-3]=b}for(d=0;18>d;d++)b=!a&&1==(c>>d&1),this.modules[d%3+this.moduleCount-8-3][Math.floor(d/3)]=b},setupTypeInfo:function(a,c){for(var d=j.getBCHTypeInfo(this.errorCorrectLevel<<3|c),b=0;15>b;b++){var e=!a&&1==(d>>b&1);6>b?this.modules[b][8]=e:8>b?this.modules[b+1][8]=e:this.modules[this.moduleCount-15+b][8]=e}for(b=0;15>b;b++)e=!a&&1==(d>>b&1),8>b?this.modules[8][this.moduleCount-
  b-1]=e:9>b?this.modules[8][15-b-1+1]=e:this.modules[8][15-b-1]=e;this.modules[this.moduleCount-8][8]=!a},mapData:function(a,c){for(var d=-1,b=this.moduleCount-1,e=7,f=0,i=this.moduleCount-1;0<i;i-=2)for(6==i&&i--;;){for(var g=0;2>g;g++)if(null==this.modules[b][i-g]){var n=!1;f<a.length&&(n=1==(a[f]>>>e&1));j.getMask(c,b,i-g)&&(n=!n);this.modules[b][i-g]=n;e--; -1==e&&(f++,e=7)}b+=d;if(0>b||this.moduleCount<=b){b-=d;d=-d;break}}}};o.PAD0=236;o.PAD1=17;o.createData=function(a,c,d){for(var c=p.getRSBlocks(a,
  c),b=new t,e=0;e<d.length;e++){var f=d[e];b.put(f.mode,4);b.put(f.getLength(),j.getLengthInBits(f.mode,a));f.write(b)}for(e=a=0;e<c.length;e++)a+=c[e].dataCount;if(b.getLengthInBits()>8*a)throw Error("code length overflow. ("+b.getLengthInBits()+">"+8*a+")");for(b.getLengthInBits()+4<=8*a&&b.put(0,4);0!=b.getLengthInBits()%8;)b.putBit(!1);for(;!(b.getLengthInBits()>=8*a);){b.put(o.PAD0,8);if(b.getLengthInBits()>=8*a)break;b.put(o.PAD1,8)}return o.createBytes(b,c)};o.createBytes=function(a,c){for(var d=
  0,b=0,e=0,f=Array(c.length),i=Array(c.length),g=0;g<c.length;g++){var n=c[g].dataCount,h=c[g].totalCount-n,b=Math.max(b,n),e=Math.max(e,h);f[g]=Array(n);for(var k=0;k<f[g].length;k++)f[g][k]=255&a.buffer[k+d];d+=n;k=j.getErrorCorrectPolynomial(h);n=(new q(f[g],k.getLength()-1)).mod(k);i[g]=Array(k.getLength()-1);for(k=0;k<i[g].length;k++)h=k+n.getLength()-i[g].length,i[g][k]=0<=h?n.get(h):0}for(k=g=0;k<c.length;k++)g+=c[k].totalCount;d=Array(g);for(k=n=0;k<b;k++)for(g=0;g<c.length;g++)k<f[g].length&&
  (d[n++]=f[g][k]);for(k=0;k<e;k++)for(g=0;g<c.length;g++)k<i[g].length&&(d[n++]=i[g][k]);return d};s=4;for(var j={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,
  78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var c=a<<10;0<=j.getBCHDigit(c)-j.getBCHDigit(j.G15);)c^=j.G15<<j.getBCHDigit(c)-j.getBCHDigit(j.G15);return(a<<10|c)^j.G15_MASK},getBCHTypeNumber:function(a){for(var c=a<<12;0<=j.getBCHDigit(c)-
  j.getBCHDigit(j.G18);)c^=j.G18<<j.getBCHDigit(c)-j.getBCHDigit(j.G18);return a<<12|c},getBCHDigit:function(a){for(var c=0;0!=a;)c++,a>>>=1;return c},getPatternPosition:function(a){return j.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,c,d){switch(a){case 0:return 0==(c+d)%2;case 1:return 0==c%2;case 2:return 0==d%3;case 3:return 0==(c+d)%3;case 4:return 0==(Math.floor(c/2)+Math.floor(d/3))%2;case 5:return 0==c*d%2+c*d%3;case 6:return 0==(c*d%2+c*d%3)%2;case 7:return 0==(c*d%3+(c+d)%2)%2;default:throw Error("bad maskPattern:"+
  a);}},getErrorCorrectPolynomial:function(a){for(var c=new q([1],0),d=0;d<a;d++)c=c.multiply(new q([1,l.gexp(d)],0));return c},getLengthInBits:function(a,c){if(1<=c&&10>c)switch(a){case 1:return 10;case 2:return 9;case s:return 8;case 8:return 8;default:throw Error("mode:"+a);}else if(27>c)switch(a){case 1:return 12;case 2:return 11;case s:return 16;case 8:return 10;default:throw Error("mode:"+a);}else if(41>c)switch(a){case 1:return 14;case 2:return 13;case s:return 16;case 8:return 12;default:throw Error("mode:"+
  a);}else throw Error("type:"+c);},getLostPoint:function(a){for(var c=a.getModuleCount(),d=0,b=0;b<c;b++)for(var e=0;e<c;e++){for(var f=0,i=a.isDark(b,e),g=-1;1>=g;g++)if(!(0>b+g||c<=b+g))for(var h=-1;1>=h;h++)0>e+h||c<=e+h||0==g&&0==h||i==a.isDark(b+g,e+h)&&f++;5<f&&(d+=3+f-5)}for(b=0;b<c-1;b++)for(e=0;e<c-1;e++)if(f=0,a.isDark(b,e)&&f++,a.isDark(b+1,e)&&f++,a.isDark(b,e+1)&&f++,a.isDark(b+1,e+1)&&f++,0==f||4==f)d+=3;for(b=0;b<c;b++)for(e=0;e<c-6;e++)a.isDark(b,e)&&!a.isDark(b,e+1)&&a.isDark(b,e+
  2)&&a.isDark(b,e+3)&&a.isDark(b,e+4)&&!a.isDark(b,e+5)&&a.isDark(b,e+6)&&(d+=40);for(e=0;e<c;e++)for(b=0;b<c-6;b++)a.isDark(b,e)&&!a.isDark(b+1,e)&&a.isDark(b+2,e)&&a.isDark(b+3,e)&&a.isDark(b+4,e)&&!a.isDark(b+5,e)&&a.isDark(b+6,e)&&(d+=40);for(e=f=0;e<c;e++)for(b=0;b<c;b++)a.isDark(b,e)&&f++;a=Math.abs(100*f/c/c-50)/5;return d+10*a}},l={glog:function(a){if(1>a)throw Error("glog("+a+")");return l.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;256<=a;)a-=255;return l.EXP_TABLE[a]},EXP_TABLE:Array(256),
  LOG_TABLE:Array(256)},m=0;8>m;m++)l.EXP_TABLE[m]=1<<m;for(m=8;256>m;m++)l.EXP_TABLE[m]=l.EXP_TABLE[m-4]^l.EXP_TABLE[m-5]^l.EXP_TABLE[m-6]^l.EXP_TABLE[m-8];for(m=0;255>m;m++)l.LOG_TABLE[l.EXP_TABLE[m]]=m;q.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var c=Array(this.getLength()+a.getLength()-1),d=0;d<this.getLength();d++)for(var b=0;b<a.getLength();b++)c[d+b]^=l.gexp(l.glog(this.get(d))+l.glog(a.get(b)));return new q(c,0)},mod:function(a){if(0>
  this.getLength()-a.getLength())return this;for(var c=l.glog(this.get(0))-l.glog(a.get(0)),d=Array(this.getLength()),b=0;b<this.getLength();b++)d[b]=this.get(b);for(b=0;b<a.getLength();b++)d[b]^=l.gexp(l.glog(a.get(b))+c);return(new q(d,0)).mod(a)}};p.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],
  [4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,
  116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,
  43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,
  3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,
  55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,
  45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];p.getRSBlocks=function(a,c){var d=p.getRsBlockTable(a,c);if(void 0==d)throw Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+c);for(var b=d.length/3,e=[],f=0;f<b;f++)for(var h=d[3*f+0],g=d[3*f+1],j=d[3*f+2],l=0;l<h;l++)e.push(new p(g,j));return e};p.getRsBlockTable=function(a,c){switch(c){case 1:return p.RS_BLOCK_TABLE[4*(a-1)+0];case 0:return p.RS_BLOCK_TABLE[4*(a-1)+1];case 3:return p.RS_BLOCK_TABLE[4*
  (a-1)+2];case 2:return p.RS_BLOCK_TABLE[4*(a-1)+3]}};t.prototype={get:function(a){return 1==(this.buffer[Math.floor(a/8)]>>>7-a%8&1)},put:function(a,c){for(var d=0;d<c;d++)this.putBit(1==(a>>>c-d-1&1))},getLengthInBits:function(){return this.length},putBit:function(a){var c=Math.floor(this.length/8);this.buffer.length<=c&&this.buffer.push(0);a&&(this.buffer[c]|=128>>>this.length%8);this.length++}};"string"===typeof h&&(h={text:h});h=r.extend({},{render:"canvas",width:256,height:256,typeNumber:-1,
  correctLevel:2,background:"#ffffff",foreground:"#000000"},h);return this.each(function(){var a;if("canvas"==h.render){a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();var c=document.createElement("canvas");c.width=h.width;c.height=h.height;for(var d=c.getContext("2d"),b=h.width/a.getModuleCount(),e=h.height/a.getModuleCount(),f=0;f<a.getModuleCount();f++)for(var i=0;i<a.getModuleCount();i++){d.fillStyle=a.isDark(f,i)?h.foreground:h.background;var g=Math.ceil((i+1)*b)-Math.floor(i*b),
  j=Math.ceil((f+1)*b)-Math.floor(f*b);d.fillRect(Math.round(i*b),Math.round(f*e),g,j)}}else{a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();c=r("<table></table>").css("width",h.width+"px").css("height",h.height+"px").css("border","0px").css("border-collapse","collapse").css("background-color",h.background);d=h.width/a.getModuleCount();b=h.height/a.getModuleCount();for(e=0;e<a.getModuleCount();e++){f=r("<tr></tr>").css("height",b+"px").appendTo(c);for(i=0;i<a.getModuleCount();i++)r("<td></td>").css("width",
  d+"px").css("background-color",a.isDark(e,i)?h.foreground:h.background).appendTo(f)}}a=c;jQuery(a).appendTo(this)})}})(jQuery);
  

});
/*!common/widgets/passport/modules/wechat-qrcode/main.js*/
;define('common/widgets/passport/modules/wechat-qrcode/main', ['require', 'exports', 'module', 'common/widgets/passport/dep/socketio-java/socket.other', 'common/widgets/passport/dep/socketio-java/moment.min', 'common/widgets/passport/dep/jquery.qrcode/jquery.qrcode.min'], function(require, exports, module) {

  // 即时通讯io
  var io = require('common/widgets/passport/dep/socketio-java/socket.other');
  require('common/widgets/passport/dep/socketio-java/moment.min');
  require('common/widgets/passport/dep/jquery.qrcode/jquery.qrcode.min');
  
  function dealURL(address) {
      var info = address.split('?') || [];
      var dealInfo = {
          url: info[0]
      };
      if (info.length > 1) {
          var infos = info[1].split('&');
          for (var i = 0, l = infos.length; i < l; i++) {
              var items = infos[i].split('=');
              dealInfo[items[0]] = items[1];
          }
      }
      return dealInfo;
  }
  
  
  function WechatQrCode(option) {
      var $wrapper = this.$wrapper = $(option.wrapper);
      this.isLogin = option.isLogin;
      this.qrCodeCanvas = $wrapper.find(".qrCodeCanvas");
      this.qrCode = $wrapper.find(".qrCode");
      this.$scanSuccess = $wrapper.find(".scan-success");
      this.$scanContent = $wrapper.find(".scan-content");
      this.authIdUrl = GLOBAL_DOMAIN.pctx + '/login/auth_id.json';
      this.qrCodeText = {
          login: function (authId) {
              return "https://weapp.lagou.com/qr/c/login?authId=" + authId
          },
          register: function (authId, registerType) {
              var registerType = registerType.toLowerCase();
              return "https://weapp.lagou.com/qr/" + registerType + "/register?authId=" + authId;
          }
      }
      this.minaCodeText = {
          login: function (authId) {
              return "https://weapp.lagou.com/api/weapp-code/pc-login-image?width=170&authId=" + authId + "&isBSide=false&isLogin=true&lineColor=rgb(0,179,138)"
          },
          register: function (authId, registerType) {
              return "https://weapp.lagou.com/api/weapp-code/pc-login-image?width=170&lineColor=rgb(0,179,138)&authId=" + authId + "&isBSide=" + (registerType === "B" ? true : false);
          }
      }
      this.succCode = 1;
      this.expireTimeId;
      this.socketInfo;
      this.socketUrl = "https://sm.lagou.com/scanQrcode";
      this.registerType = "C";
  }
  
  WechatQrCode.prototype.openQrCode = function (option) {
      var _this = this;
      if (option) {
          _this.registerType = option.registerType;
      }
      _this.closeQrCode();
      _this.getAuthId();
  }
  
  WechatQrCode.prototype.closeQrCode = function () {
      var _this = this;
      var expireTimeId = _this.expireTimeId;
      var socketInfo = _this.socketInfo;
      expireTimeId && clearTimeout(expireTimeId);
      socketInfo && socketInfo.close();
  }
  
  WechatQrCode.prototype.getQrCodeText = function (authId) {
      var _this = this;
      var registerType = _this.registerType;
      if (_this.isLogin) {
          return _this.qrCodeText.login(authId);
      }
      return _this.qrCodeText.register(authId, registerType);
  }
  
  WechatQrCode.prototype.getMinaCodeText = function (authId) {
      var _this = this;
      var registerType = _this.registerType;
      if (_this.isLogin) {
          return _this.minaCodeText.login(authId);
      }
      return _this.minaCodeText.register(authId, registerType);
  }
  
  WechatQrCode.prototype.getAuthId = function () {
      var _this = this;
      var succCode = _this.succCode;
      var qrCode = _this.qrCode;
      var qrCodeCanvas = _this.qrCodeCanvas;
      if (_this.expireTimeId) {
          clearTimeout(_this.expireTimeId);
          _this.socketInfo.close();
          _this.$scanSuccess.hide();
          _this.$scanContent.css({
              opacity: 1
          });
      }
      $.ajax({
          url: GLOBAL_DOMAIN.pctx + '/login/auth_id.json',
          // xhrFields: {
          //     withCredentials: true
          // },
          dataType: "jsonp",
          jsonp: "jsoncallback",
      }).done(function (result) {
          if (result.state === succCode) {
              _this.getSocket();
              var data = result.content.data;
              var time = 1000;
  
              _this.expireTimeId = setTimeout(function () {
                  clearTimeout(_this.expireTimeId);
                  _this.getAuthId();
                  _this.$scanSuccess.hide();
                  _this.$scanContent.css({
                      opacity: 1
                  });
              }, data.expireSeconds * time);
          }
  
          if (data.isQRCode) {
              qrCode.hide();
              var text = _this.getQrCodeText(data.authId);
              qrCodeCanvas.html('');
              qrCodeCanvas.qrcode({
                  render: "canvas",
                  text: text,
                  width: 180,
                  height: 180,
                  correctLevel: 3,
                  foreground: "#000000"
              });
              qrCodeCanvas.attr('title', text);
              qrCodeCanvas.show();
          } else {
              var src = _this.getMinaCodeText(data.authId);
              qrCodeCanvas.hide();
              qrCode.attr('src', src);
              qrCode.show();
          }
      })
  }
  
  WechatQrCode.prototype.getSocket = function () {
      var _this = this;
      var socketUrl = _this.socketUrl;
      var $scanSuccess = _this.$scanSuccess;
      var $scanContent = _this.$scanContent;
      var expireTimeId = _this.expireTimeId;
      var socketInfo = io.connect(socketUrl, {
          "path": "/push",
          "force new connection": true,
          "reconnection": true,
          "reconnectionDelay": 2000,
          "reconnectionDelayMax": 5000,
          "reconnectionAttempts": "Infinity",
          "timeout": 10000,
          "transports": ["polling", "websocket"],
          "query": {
              "uri": window.location.pathname
          }
      });
  
      socketInfo.on('scanQrcode', function (data) {
          var json = JSON.parse(data);
          var succCode = _this.succCode;
          var content = json.content;
          // 扫码成功
          if (json.type === succCode) {
              $scanSuccess.show();
              $scanContent.css({
                  opacity: 0
              });
          }
          else if (json.type === 0) {
              if (/callback/.test(content)) {
                  window.location.href = content;
              }
              else {
                  // 取 service
                  var href = window.location.href;
                  href = dealURL(href);
                  if (href.service) {
                      var hrefInfo = href.service.split('.com');
                      if (/lagou/.test(hrefInfo[0])) {
                          window.location.href = content + '&callback=' + href.service;
                      }
                      else {
                          window.location.href = content + '&callback=' + encodeURIComponent(window.location.href);
                      }
                  }
                  else {
                      window.location.href = content + '&callback=' + encodeURIComponent(window.location.href);;
                  }
              }
          }
      });
      socketInfo.on('connect_error', function () {
          clearTimeout(expireTimeId);
          $scanSuccess.hide();
          $scanContent.css({
              opacity: 1
          });
          socketInfo.close();
      });
      _this.socketInfo = socketInfo;
  }
  
  
  module.exports = WechatQrCode;

});
/*!common/components/modal/modal.js*/
;define('common/components/modal/modal', ['require', 'exports', 'module'], function(require, exports, module) {

  /* ========================================================================
   * Bootstrap: modal.js v3.3.7
   * http://getbootstrap.com/javascript/#modals
   * ========================================================================
   * Copyright 2011-2016 Twitter, Inc.
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   * ======================================================================== */
  
  
  +function ($) {
      'use strict';
    
      // MODAL CLASS DEFINITION
      // ======================
    
      var Modal = function (element, options) {
        this.options             = options
        this.$body               = $(document.body)
        this.$element            = $(element)
        this.$dialog             = this.$element.find('.modal-dialog')
        this.$backdrop           = null
        this.isShown             = null
        this.originalBodyPad     = null
        this.scrollbarWidth      = 0
        this.ignoreBackdropClick = false
    
        if (this.options.remote) {
          this.$element
            .find('.modal-content')
            .load(this.options.remote, $.proxy(function () {
              this.$element.trigger('loaded.bs.modal')
            }, this))
        }
      }
    
      Modal.VERSION  = '3.3.7'
    
      Modal.TRANSITION_DURATION = 300
      Modal.BACKDROP_TRANSITION_DURATION = 150
    
      Modal.DEFAULTS = {
        backdrop: true,
        keyboard: true,
        show: true
      }
    
      Modal.prototype.toggle = function (_relatedTarget) {
        return this.isShown ? this.hide() : this.show(_relatedTarget)
      }
    
      Modal.prototype.show = function (_relatedTarget) {
        var that = this
        var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
    
        this.$element.trigger(e)
    
        if (this.isShown || e.isDefaultPrevented()) return
    
        this.isShown = true
    
        this.checkScrollbar()
        this.setScrollbar()
        this.$body.addClass('modal-open')
    
        this.escape()
        this.resize()
    
        this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
    
        this.$dialog.on('mousedown.dismiss.bs.modal', function () {
          that.$element.one('mouseup.dismiss.bs.modal', function (e) {
            if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
          })
        })
    
        this.backdrop(function () {
          var transition = $.support.transition && that.$element.hasClass('fade')
    
          if (!that.$element.parent().length) {
            that.$element.appendTo(that.$body) // don't move modals dom position
          }
    
          that.$element
            .show()
            .scrollTop(0)
    
          that.adjustDialog()
    
          if (transition) {
            that.$element[0].offsetWidth // force reflow
          }
    
          that.$element.addClass('in')
    
          that.enforceFocus()
    
          var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
    
          transition ?
            that.$dialog // wait for modal to slide in
              .one('bsTransitionEnd', function () {
                that.$element.trigger('focus').trigger(e)
              })
              .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
            that.$element.trigger('focus').trigger(e)
        })
      }
    
      Modal.prototype.hide = function (e) {
        if (e) e.preventDefault()
    
        e = $.Event('hide.bs.modal')
    
        this.$element.trigger(e)
    
        if (!this.isShown || e.isDefaultPrevented()) return
    
        this.isShown = false
    
        this.escape()
        this.resize()
    
        $(document).off('focusin.bs.modal')
    
        this.$element
          .removeClass('in')
          .off('click.dismiss.bs.modal')
          .off('mouseup.dismiss.bs.modal')
    
        this.$dialog.off('mousedown.dismiss.bs.modal')
    
        $.support.transition && this.$element.hasClass('fade') ?
          this.$element
            .one('bsTransitionEnd', $.proxy(this.hideModal, this))
            .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
          this.hideModal()
      }
    
      Modal.prototype.enforceFocus = function () {
        $(document)
          .off('focusin.bs.modal') // guard against infinite focus loop
          .on('focusin.bs.modal', $.proxy(function (e) {
            if (document !== e.target &&
                this.$element[0] !== e.target &&
                !this.$element.has(e.target).length) {
              this.$element.trigger('focus')
            }
          }, this))
      }
    
      Modal.prototype.escape = function () {
        if (this.isShown && this.options.keyboard) {
          this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
            e.which == 27 && this.hide()
          }, this))
        } else if (!this.isShown) {
          this.$element.off('keydown.dismiss.bs.modal')
        }
      }
    
      Modal.prototype.resize = function () {
        if (this.isShown) {
          $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
        } else {
          $(window).off('resize.bs.modal')
        }
      }
    
      Modal.prototype.hideModal = function () {
        var that = this
        this.$element.hide()
        this.backdrop(function () {
          that.$body.removeClass('modal-open')
          that.resetAdjustments()
          that.resetScrollbar()
          that.$element.trigger('hidden.bs.modal')
        })
      }
    
      Modal.prototype.removeBackdrop = function () {
        this.$backdrop && this.$backdrop.remove()
        this.$backdrop = null
      }
    
      Modal.prototype.backdrop = function (callback) {
        var that = this
        var animate = this.$element.hasClass('fade') ? 'fade' : ''
        if (this.isShown && this.options.backdrop) {
          var doAnimate = $.support.transition && animate
    
          this.$backdrop = $(document.createElement('div'))
            .addClass('modal-backdrop ' + animate)
            .appendTo(this.$element)
    
          this.$backdrop.on('click.dismiss.bs.modal', $.proxy(function (e) {
            if (this.ignoreBackdropClick) {
              this.ignoreBackdropClick = false
              return
            }
            if (e.target !== e.currentTarget) return
            this.options.backdrop == 'static'
              ? this.$element[0].focus()
              : this.hide()
          }, this))
    
          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
    
          this.$backdrop.addClass('in')
    
          if (!callback) return
    
          doAnimate ?
            this.$backdrop
              .one('bsTransitionEnd', callback)
              .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
            callback()
    
        } else if (!this.isShown && this.$backdrop) {
          this.$backdrop.removeClass('in')
    
          var callbackRemove = function () {
            that.removeBackdrop()
            callback && callback()
          }
          $.support.transition && this.$element.hasClass('fade') ?
            this.$backdrop
              .one('bsTransitionEnd', callbackRemove)
              .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
            callbackRemove()
    
        } else if (callback) {
          callback()
        }
      }
    
      // these following methods are used to handle overflowing modals
    
      Modal.prototype.handleUpdate = function () {
        this.adjustDialog()
      }
    
      Modal.prototype.adjustDialog = function () {
        var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
    
        this.$element.css({
          paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
          paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
        })
      }
    
      Modal.prototype.resetAdjustments = function () {
        this.$element.css({
          paddingLeft: '',
          paddingRight: ''
        })
      }
    
      Modal.prototype.checkScrollbar = function () {
        var fullWindowWidth = window.innerWidth
        if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
          var documentElementRect = document.documentElement.getBoundingClientRect()
          fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
        }
        this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
        this.scrollbarWidth = this.measureScrollbar()
      }
    
      Modal.prototype.setScrollbar = function () {
        var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
        this.originalBodyPad = document.body.style.paddingRight || ''
        if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
      }
    
      Modal.prototype.resetScrollbar = function () {
        this.$body.css('padding-right', this.originalBodyPad)
      }
    
      Modal.prototype.measureScrollbar = function () { // thx walsh
        var scrollDiv = document.createElement('div')
        scrollDiv.className = 'modal-scrollbar-measure'
        this.$body.append(scrollDiv)
        var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
        this.$body[0].removeChild(scrollDiv)
        return scrollbarWidth
      }
    
    
      // MODAL PLUGIN DEFINITION
      // =======================
    
      function Plugin(option, _relatedTarget) {
        return this.each(function () {
          var $this   = $(this)
          var data    = $this.data('bs.modal')
          var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
    
          if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
          if (typeof option == 'string') data[option](_relatedTarget)
          else if (options.show) data.show(_relatedTarget)
        })
      }
    
      var old = $.fn.modal
    
      $.fn.modal             = Plugin
      $.fn.modal.Constructor = Modal
    
    
      // MODAL NO CONFLICT
      // =================
    
      $.fn.modal.noConflict = function () {
        $.fn.modal = old
        return this
      }
    
    
      // MODAL DATA-API
      // ==============
    
      $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
        var $this   = $(this)
        var href    = $this.attr('href')
        var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
        var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
    
        if ($this.is('a')) e.preventDefault()
    
        $target.one('show.bs.modal', function (showEvent) {
          if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
          $target.one('hidden.bs.modal', function () {
            $this.is(':visible') && $this.trigger('focus')
          })
        })
        Plugin.call($target, option, this)
      })
    
    }(jQuery);
    

});
/*!common/widgets/passport/common/js/lagou.js*/
;define('common/widgets/passport/common/js/lagou', ['require', 'exports', 'module'], function(require, exports, module) {

  /**
   * Created by storm on 15/9/25.
   */
  
  /** ----------------------------------------------------------------- start
   *命名空间
   *
   */
  
  
  var lg = window.lg || {};
  /**
   * lg={}
   * {
   *      Utils
   *      Widgets
   *      Views
   *      Models
   *      Cache
   *      TempletEngine
   *      Routers
   *      Events
   *      .
   *      .
   *      .
   * }
   */
  if (!Array.prototype.indexOf)
  {
    Array.prototype.indexOf = function(elt /*, from*/)
    {
      var len = this.length >>> 0;
  
      var from = Number(arguments[1]) || 0;
      from = (from < 0)
           ? Math.ceil(from)
           : Math.floor(from);
      if (from < 0)
        from += len;
      for (; from < len; from++)
      {
        if (from in this &&
            this[from] === elt)
          return from;
      }
      return -1;
    };
  }
  if(!String.prototype.trim){
      String.prototype.trim=function(){
  　　    return this.replace(/(^\s*)|(\s*$)/g, "");
  　　 }
  　　 String.prototype.ltrim=function(){
  　　    return this.replace(/(^\s*)/g,"");
  　　 }
  　　 String.prototype.rtrim=function(){
  　　    return this.replace(/(\s*$)/g,"");
  　　 }
  }
  
  lg.Event = lg.Event || {};
  
  lg.Event._events = {};
  lg.Event.on = function(eventName, data, func) {
      this._events[eventName] = this._events[eventName] || []
      this._events[eventName].push({
          data: data,
          func: func
      });
      return this;
  
  }
  lg.Event.un = function(eventName, func) {
      var events = this._events;
  
      // 移除所有事件
      if (0 === arguments.length) {
          this._events = {};
          return this;
      }
  
      var listeners = events[eventName];
      if (!listeners) {
          return this;
      }
  
      // 移除指定事件下的所有监听器
      if (1 === arguments.length) {
          delete events[eventName];
          return this;
      }
  
      // 移除指定监听器（包括对once的处理）
      var cb;
      for (var i = 0; i < listeners.length; i++) {
          cb = listeners[i];
          if (cb === listener || cb.listener === listener) {
              listeners.splice(i, 1);
              break;
          }
      }
      return this;
  };
  
  lg.Event.exec = function(eventName) {
      var events = this._events;
      var listeners = events[eventName];
      var args = Array.prototype.slice.call(arguments, 1);
  
      if (listeners) {
          listeners = listeners.slice(0);
          for (var i = 0, len = listeners.length; i < len; i++) {
              listeners[i].apply(this, args);
          }
      }
      return this;
  };
  
  
  
  
  lg.Cache = lg.Cache || {};
  lg.Cache.Views = lg.Cache.Views || {};
  
  /**-----------------------------------------------------------------  start
   * 公共工具箱
   */
  
  lg.Utils = lg.Utils || {};
  /**
   * lg.Utils={}
   * {
   *      getNewId()
   *      Formate()
   *      .
   *      .
   *      .
   * }
   */
  
  /**
   * 判断对象val 是否等于 {}
   * @param val
   * @returns {boolean}
   */
  lg.Utils.isNullObject = function(val) {
      if (typeof val === "object" && !(val instanceof Array)) {
          var hasProp = false;
          for (var prop in val) {
              hasProp = true;
              break;
          }
          return hasProp;
      }
  }
  
  //------------------------------------------------------------------  end
  
  
  /**-----------------------------------------------------------------  start
   * 命名控件 - 控件
   */
  
  lg.Widgets = lg.Widgets || {};
  
  /**
   * 控件基础够着函数
   * @param options
   * @constructor
   */
  lg.Widgets.BaseControl = function(options) {
      this._name = '';
      this._option = {};
      this.Event = lg.Event;
      this._data = {};
      this._value = '';
      this._isDirty = false;
      this._isValueField = true;
      this._data.valid = this._data.valid || {};
      this._data.valid.validResult = {};
      this._data.valid._map = {
          require: {
              mode: 'require',
              isUse: false,
              status: false,
              data: '',
              message: '必填',
              level:'3',
              trigger: []
          },
          re_pwd: {
              mode: 'repeat-password',
              isUse: false,
              status: false,
              data: '',
              message: '',
              level:'2',
              trigger: []
          },
          min_len: {
              mode: 'min-length',
              isUse: false,
              status: false,
              data: '',
              message: '最小长度',
              level:'1',
              trigger: []
          },
          max_len: {
              mode: 'max-length',
              isUse: false,
              status: false,
              data: '',
              message: '最大长度',
              level:'1',
              trigger: []
  
          },
          pattern: {
              mode: 'pattern',
              isUse: false,
              status: false,
              data: '',
              message: '',
              level:'2',
              trigger: []
          }
      }
      $.extend(this._option, options);
      if (this._option.validRules) {
          for (var i = 0, len = this._option.validRules.length; i < len; i++) {
              var item = this._option.validRules[i];
              if (this._data.valid._map[item.mode]) {
                  this._data.valid._map[item.mode].isUse = true;
                  this._data.valid._map[item.mode].data = item.data;
                  this._data.valid._map[item.mode].message = item.message;
                  this._data.valid._map[item.mode].level = item.level||this._data.valid._map[item.mode].level;
  
              } else {
                  this._data.valid._map[item.mode] = {
                      mode: item.mode,
                      isUse: true,
                      status: false,
                      data: item.data,
                      message: item.message,
                      level:0
                  }
              }
              if (item.trigger) {
                  this._data.valid._map[item.mode].trigger = item.trigger.split(',');
              } else {
                  this._data.valid._map[item.mode].trigger.push('blur');
              }
          }
      }
      this._selector = '[data-view="' + this._option.parentName + '"] [data-propertyname="' + this._option.name + '"]'
      this._element = typeof this._option.name == 'string' ? $(this._selector) : this._option.name;
      typeof this.init == 'function' ? this.init() : '';
  }
  /**
   * 获取是否是输入值的域
   * @returns {string}
   */
  lg.Widgets.BaseControl.prototype.getIsValueField = function() {
      return this._isValueField;
  }
  lg.Widgets.BaseControl.prototype.setIsValueField = function(val) {
      var value = false;
      if (val) {
          value = true;
      }
      this._isValueField = value;
  }
  /**
   * 获取控件实例名
   * @returns {string}
   */
  lg.Widgets.BaseControl.prototype.getName = function() {
      return this._option.name;
  }
  lg.Widgets.BaseControl.prototype.getElement = function() {
      return this._element;
  }
      /**
       * 初始化控件
       * @param options
       */
  lg.Widgets.BaseControl.prototype.BaseInit = function(options) {
      this.setData(options); //初始化控件参数
      var that = this;
      var isVisible = true;
      if(!this._option.isFocusShow){
          this.getElement().find('input[type="text"],input[type="password"],input[type="checkbox"],input.btn_outline').on('focus', function(e) {
              that.setValidMessage();
              that.getElement().addClass("focus");
          });
      }
      typeof this._option.isVisible == 'undefined'?isVisible:isVisible=false;
      this.setVisible(isVisible);
      
      this.getElement().find('input[type="text"],input[type="password"]').on('blur',{control: this}, function(e) {
          var that = e.data.control;
          that.getElement().removeClass("focus");
      });
      //验证触发事件定义    ==> keyup blur
      this.getElement().find('input[type="text"],input[type="password"]').on('blur keydown change keyup', {control: this},function(e) {
          var that = e.data.control;
          if (e.type == 'keydown') {
              that._isDirty = true;
          }
          var value = that.getValue();
          var validResult = that.getIsValid(value, e.type);
          if(that._isDirty&& that.getSelfIsValided()&&(e.type=="keyup"||e.type=="change")){
              
              if(that._option.keyup){
                  that.execValid(that.getValue());
                  that._option.keyup.call(this, {
                  control: that,
                  isValidat:true,
                  parent: lg.Cache.Views[that._option.parentName],
                  linkFor:lg.Cache.Views[that._option.parentName].field[that._option.linkFor]
              })
              }
          }else if(that._isDirty&& !that.getSelfIsValided()&&(e.type=="keyup"||e.type=="change")){
             
              if(that._option.keyup){
                  that.execValid(that.getValue());
                  that._option.keyup.call(this, {
                  control: that,
                  isValidat:false,
                  parent: lg.Cache.Views[that._option.parentName],
                  linkFor:lg.Cache.Views[that._option.parentName].field[that._option.linkFor]
              })
              }
          }
          if (lg.Utils.isNullObject(validResult)) {
              that.setValidMessage(validResult);
              return;
          } else {
              that.setValidMessage();
          }
          
      });
  }
  
  lg.Widgets.BaseControl.prototype.showMessage = function(val){
      this.getElement().find('[data-valid-message]').length ? '' : this.getElement().append('<span data-valid-message class="input_tips"></span>');
      var messageBox = this.getElement().find('[data-valid-message]');
      var message = messageBox.html();
      if (lg.Utils.isNullObject(val)) {
          messageBox.empty();
          var messageList = '';
          
          messageBox.html(val.message);
          messageBox.show();
          this.getElement().find('input[type="text"]').addClass('input_warning');
          this.getElement().find('input[type="password"]').addClass('input_warning');
      } else {
          messageBox.remove();
          this.getElement().find('input[type="text"]').removeClass('input_warning');
          this.getElement().find('input[type="password"]').removeClass('input_warning');
      }   
  }
  lg.Widgets.BaseControl.prototype.setValidMessage = function(val,from) {
          if(this._option.forbidAddMessageBySelf){
              if(from=="CollectData"){
                  this.getElement().find('[data-valid-message]').length ?'' : this.getElement().append('<span data-valid-message class="input_tips"></span>');
                  var messageBox = this.getElement().find('[data-valid-message]');
              }else{
                  var messageBox = this.getElement().find('[data-valid-message]');
                  if(!messageBox && messageBox.length>0){
                      return;
                  }
              }
              
          }else{
              this.getElement().find('[data-valid-message]').length ?'' : this.getElement().append('<span data-valid-message class="input_tips"></span>');
              var messageBox = this.getElement().find('[data-valid-message]');
          }
          
  
          var message = messageBox.html();
          if (lg.Utils.isNullObject(val || {})) {
              messageBox.empty();
              var messageList = '';
              var level = 0;
              for (var item in val) {
                  typeof val[item].level !='undefined'?(level = (level<val[item].level)?val[item].level:level):'';
              }
              for (var item in val) {
                  if(typeof val[item].level !='undefined'&& level == val[item].level){
                      messageList = val[item].message;
                  }
              }
              messageBox.html(messageList);
              messageBox.show();
              this.getElement().find('input[type="text"]').addClass('input_warning');
              this.getElement().find('input[type="password"]').addClass('input_warning');
          } else {
              messageBox.remove();
              this.getElement().find('input[type="text"]').removeClass('input_warning');
              this.getElement().find('input[type="password"]').removeClass('input_warning');
          }
      }
      /**
       *设置控件参数
       * @param data
       */
  lg.Widgets.BaseControl.prototype.setData = function(data) {
      for (var item in data) {
          this['set' + item] = data[item];
      }
  }
  
      /**
       *初始化
       * @param data
       */
  lg.Widgets.BaseControl.prototype.setClear = function() {
  
      this.getElement().find('input.input_warning').removeClass('input_warning');
      this.getElement().find('[data-valid-message]').remove();
      this.getElement().find('input[type="text"],input[type="password"]').val('');
      this._isDirty = false;
      this.getElement().find('input[type="text"],input[type="password"]').blur();
  }
  
  /**
   * 获取控件是否只读
   * @returns {boolean}
   */
  lg.Widgets.BaseControl.prototype.getIsReadOnly = function() {
      return this.getElement().attr('readonly') ? true : false;
  }
  
  /**
   * 设置控件是否只读
   * @param val
   */
  lg.Widgets.BaseControl.prototype.setReadOnly = function(val) {
      var value = false;
      if (val) {
          value = true;
      }
      value ? this.getElement().attr('readonly', value) : this.getElement().removeAttr('readonly');
  }
  
  /**
   * 获取控件是否可用
   * @returns {boolean}
   */
  lg.Widgets.BaseControl.prototype.getIsDisabled = function() {
      return this.getElement().attr('disabled') ? true : false;
  }
  
  /**
   * 设置是否获取焦点
   * @param val
   * @returns {*}
   */
  lg.Widgets.BaseControl.prototype.setFocus = function(val) {
          var value = false;
          if (val) {
              value = true;
              this.getElement().find('input[type ="text"]').focus();
          }
          //this.getElement().find('input[text]').focus();
      }
      /**
       * 设置控件是否可用
       * @param val
       */
  lg.Widgets.BaseControl.prototype.setDisable = function(val) {
      var value = false;
      if (val) {
          value = true;
      }
      value ? this.getElement().attr('disabled', value) : this.getElement().removeAttr('disabled');
      if(value){
          this.getElement().attr('disabled', value);
          this.getElement().find('input[type="button"]').attr('disabled', value);
      }else{
          this.getElement().removeAttr('disabled');
          this.getElement().find('input[type="button"]').removeAttr('disabled');
      }
  }
  
  /**
   * 获取控件是否可见
   * @returns {boolean}
   */
  lg.Widgets.BaseControl.prototype.getIsVisible = function() {
      return this.getElement().css('display') != 'none' ? true : false;
  }
  
  /**
   * 设置控件是否可见
   * @param val
   */
  lg.Widgets.BaseControl.prototype.setVisible = function(val) {
      var value = 'none';
      if (val) {
          value = 'block';
      }
      this.getElement().css('display', value);
  }
  
  /**
   * 获取验证结果
   * @returns {Array}
   */
  lg.Widgets.BaseControl.prototype.getIsValid = function(val, type) {
      this.execValid(val, type);
      return this._data.valid.validResult;
  }
  
  /**
   * 设置控件验证规则
   * @param val
   */
  lg.Widgets.BaseControl.prototype.setValid = function(val) {
          for (var item in val) {
              this._data.valid._map[item].is = val[item];
          }
      }
      /**
       * 获取值
       * @param val
       */
  lg.Widgets.BaseControl.prototype.getValue = function() {
      this._value = typeof this.getElement().find('input[type="text"]').val() == 'undefined' ? this.getElement().find('input[type="password"]').val() : this.getElement().find('input[type="text"]').val();
      this._value = typeof this._value =='undefined'?'':this._value;
      this._value = this._value.trim();
      return this._value;
  }
  
  lg.Widgets.BaseControl.prototype.setValue = function(val) {
          this._value = this.getElement().find('input[type="text"]').val(val) || this.getElement().find('input[type="password"]').val(val);
      }
      /**
       * 执行验证规则
       * @param val
       */
  lg.Widgets.BaseControl.prototype.execValid = function(val, type) {
      var thisType = type || 'blur';
      if (typeof val == 'undefined' || !this.getIsVisible()) return;
      for (var item in this._data.valid._map) {
          if (typeof this._data.valid._map[item] == 'object') {
              if (this._data.valid._map[item].isUse) {
                  if (this._data.valid._map[item].mode == 'require') {
                      this.controlValidResult((val.length == 0)&&this._isDirty&&(this._data.valid._map[item].trigger.indexOf(thisType) > -1), item,type);
                  }
                  if (this._data.valid._map[item].mode == 'min-len') {
                      this.controlValidResult((val.length < this._data.valid._map[item].data) && this._isDirty && (this._data.valid._map[item].trigger.indexOf(thisType) > -1), item,type);
                  }
                  if (this._data.valid._map[item].mode == 'max-len') {
                      this.controlValidResult((val.length > this._data.valid._map[item].data) && this._isDirty && (this._data.valid._map[item].trigger.indexOf(thisType) > -1), item,type);
                  }
                  if (this._data.valid._map[item].mode == 'repeat-password') {
                      var pwd = lg.Cache.Views[this._option.parentName].field[this._option.linkFor].getValue();
                      var repwd = this.getValue();
                      this.controlValidResult((pwd != repwd) && this._isDirty && (this._data.valid._map[item].trigger.indexOf(thisType) > -1), item ,type);
                  }
                  if (this._data.valid._map[item].mode == 'pattern') {
                     
                      if(typeof this._data.valid._map[item].data=='string'){
                          var data = this._data.valid._map[item].data.split('||');
                          var temp = false;
                          for(var i=0,len=data.length;i<len;i++){
                              var reg = eval(data[i]);
                              temp = temp || reg.test(val);    
                          }         
                      }else{
                          var data = this._data.valid._map[item].data;
                          var temp = false;
                           for(var i in data){
                              if(typeof data[i] !='function'){
                                  temp = temp || data[i].test(val);
                              }
                          }   
                      }
                          this.controlValidResult((!temp) && this._isDirty && (this._data.valid._map[item].trigger.indexOf(thisType) > -1), item,type);
                  }
              }
          }
  
      }
  }
  lg.Widgets.BaseControl.prototype.getSelfIsValided = function() {
      var value = true;
      var val = this.getValue();
      if (typeof val == 'undefined') return false;
      for (var item in this._data.valid._map) {
          if (typeof this._data.valid._map[item] == 'object') {
              if (this._data.valid._map[item].isUse) {
                  if (this._data.valid._map[item].mode == 'require') {
                       value && (val.length != 0)?value=true:value=false;
                  }
                  if (this._data.valid._map[item].mode == 'min-len') {
                       value && (val.length > this._data.valid._map[item].data)?value=true:value=false;
                  }
                  if (this._data.valid._map[item].mode == 'max-len') {
                      value && (val.length < this._data.valid._map[item].data)?value=true:value=false;
                  }
                  if (this._data.valid._map[item].mode == 'repeat-password') {
                      var pwd = lg.Cache.Views[this._option.parentName].field[this._option.linkFor].getValue();
                      var repwd = this.getValue();
                      value && (pwd == repwd)?value=true:value=false;
                  }
                  if (this._data.valid._map[item].mode == 'pattern') {
                      if(typeof this._data.valid._map[item].data=='string'){
                          var data = this._data.valid._map[item].data.split('||');
                          var temp = false;
                          for(var i=0,len=data.length;i<len;i++){
                              var reg = eval(data[i]);
                              temp = temp || reg.test(val);    
                          }         
                      }else{
                          var data = this._data.valid._map[item].data;
                          var temp = false;
                           for(var i in data){
                              if(typeof data[i] !='function'){
                                  temp = temp || data[i].test(val);
                              }
                          }   
                      }
                      value && temp ? value=true:value=false;
                     
                  }
              }
          }
  
      }
      return value;
  }
  lg.Widgets.BaseControl.prototype.controlValidResult = function(val, item , type) {
      //var result = type ==""
      if(!!val){
          this._data.valid.validResult[this._data.valid._map[item].mode] = this._data.valid._map[item];
          this._data.valid.validResult[this._data.valid._map[item].mode].triggerType = type;
      }else{
          delete this._data.valid.validResult[this._data.valid._map[item].mode]
      }
  }
  lg.Widgets.Controls = {};
  lg.Widgets.Controls.Phone = function(controlType, func) {
      lg.Widgets.Controls[controlType] = func(controlType);
  };
  
  lg.Widgets.Controls.Extend = function(controlType, func) {
      lg.Widgets.Controls[controlType] = func(controlType);
  };
  
  lg.Widgets.Controls.Extend("Phone", function(controlType) {
      var _shieldChar;
      var control = function(id, options) {
          lg.Widgets.BaseControl.call(this, id, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      return control;
  });
  
  lg.Widgets.Controls.Extend("PhoneVerificationCode", function(controlType) {
      var _shieldChar;
      var control = function(id, options) {
          lg.Widgets.BaseControl.call(this, id, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
  
      /**
       * 获取设置的时长
       * @returns {number|*}
       */
      control.prototype.getTopTime = function() {
          return this._option.topTime || 60;
      }
  
      /**
       * 设置总时长
       * @param val
       */
      control.prototype.setTopTime = function(val) {
          this._option.topTime = val;
      }
  
      /**
       *获取验证码获取总次数
       * @returns {*}
       */
      control.prototype.getopCount = function() {
          return this._option.topCount || null;
      }
      control.prototype.getTotalCount = function(val) {
          return this._option.totalCount;
      }
      control.prototype.setTotalTimeTemp = function() {
          this.totalTimeTemp = this.getTopTime();
      }
      control.prototype.setTimeLine = function(val) {
          this._option.timeLine = val;
      }
      control.prototype.getPhoneVerificationCodeUrl = function() {
          return this._option.url;
      }
      control.prototype.getVerificationButton = function() {
          return this.getElement().find('input[type="button"]');
      }
  
      control.prototype.getVerificationInput = function() {
          return this.getElement().find('input[type="text"]');
      }
      control.prototype.getCodeIsDisabled = function() {
          return this.getElement().find('input[type="button"]').hasClass('btn_disabled');
      }
      control.prototype.setCodeIsDisabled = function(val) {
          var value = false;
          if(val){
              value = true;
              this.getElement().find('input[type="button"]').addClass('btn_disabled');
              return value;
          }else{
              this.getElement().find('input[type="button"]').removeClass('btn_disabled');
              return value;
          }
          
      }
      control.prototype.getLinkFor = function() {
          return lg.Cache.Views[this._option.parentName].field[this._option.linkFor];
      }
      control.prototype.init = function() {
          //this.count = this.getTotalCount();
          clearInterval(this.timeLine);
          this.timeLine = null;
          this.isActive = false;
          //var that = this;
          //if(this._option.codeIsDisabled){
          this.setCodeIsDisabled(this._option.codeIsDisabled);
          //}
          
          var linkFor = lg.Cache.Views[this._option.parentName].field[this._option.linkFor];
  
          if(!linkFor.getSelfIsValided()&&linkFor._option.keyup){
              this.getVerificationButton().val((typeof this._option.postfix!='string')?'获取验证码':'获取');
              
          }else if(linkFor.getSelfIsValided()&&linkFor._option.keyup){
              this.getVerificationButton().removeClass('btn_disabled').val((typeof this._option.postfix!='string')?'获取验证码':'获取');
          }
          this.totalTimeTemp = this.getTopTime();
          this.getElement().find('input[type="button"]').one('click', {
              control: this
          }, function(e) {
              var that = e.data.control; 
              var isValidateLinkAndVerifyCode = true;
              var linkFor = lg.Cache.Views[that._option.parentName].field[that._option.linkFor];
              var verifyCode = lg.Cache.Views[that._option.parentName].field[that._option.verifyCode];
              if(verifyCode.getIsVisible()){
                  verifyCode.getSelfIsValided()&&isValidateLinkAndVerifyCode?isValidateLinkAndVerifyCode=true:isValidateLinkAndVerifyCode=false;
              }
              linkFor.getSelfIsValided()&&isValidateLinkAndVerifyCode?isValidateLinkAndVerifyCode=true:isValidateLinkAndVerifyCode=false;
              if(isValidateLinkAndVerifyCode){
                  that.setDisable(true);
                  if(!that.getCodeIsDisabled()&& that.getIsDisabled()){
                          that.isActive = true;
                          that._option.click.call(this, {
                              control: that,
                              parent: lg.Cache.Views[that._option.parentName],
                              linkFor:linkFor
                          })
                     
                      
                  }
              }else{
  
                  linkFor._isDirty=true;
                  linkFor.setValidMessage(linkFor.getIsValid(linkFor.getValue()),'CollectData');
                  if(verifyCode.getIsVisible()){
                      verifyCode._isDirty=true;
                      verifyCode.setValidMessage(verifyCode.getIsValid(verifyCode.getValue()),'CollectData');
                  }
                  that.init();
              }
             
              //e.data.control.starttime(e.data.control);
          });
      }
      control.prototype.getVerificationCode = function(){
  
      }
      control.prototype.setClear = function() {
  
          this.getElement().find('input.input_warning').removeClass('input_warning');
          this.getElement().find('[data-valid-message]').remove();
          this.getElement().find('input[type="text"],input[type="password"]').val('');
          this._isDirty = false;
          this.getElement().find('input[type="text"],input[type="password"]').blur();
          
          var objEvt = $._data(this.getElement().find('input[type="button"]')[0], "events");
          if (objEvt && objEvt["click"]) {
              //console.info(objEvt["click"]);
              //alert("bind click");
          }
          else {
              this.init();
          }
          this.timeLine  && clearInterval(this.timeLine);
          this.timeLine = null;
          this.setDisable(false);
          var linkFor = lg.Cache.Views[this._option.parentName].field[this._option.linkFor];
          if(!linkFor.getSelfIsValided()&&linkFor._option.keyup){
              //this.init();
              this.getVerificationButton().val((typeof this._option.postfix!='string')?'获取验证码':'获取');
              
          }else{
              //this.init();
  
              this.getVerificationButton().removeClass('btn_disabled').val((typeof this._option.postfix!='string')?'获取验证码':'获取');
              
          }
      }
      control.prototype.starttime = function(that, cb) {
          if (!that.timeLine) {
              that.totalTimeTemp = that.getTopTime();
              
              that.timeLine = setInterval(function() {
                  var self = lg.Cache.Views[that._option.parentName].field[that.getName()];
                  self.totalTimeTemp--;
                  var text = (typeof self._option.postfix!='string')?'秒后重试':self._option.postfix+'s';
                  self.getVerificationButton().addClass('btn_disabled').val(self.totalTimeTemp + text);
                  if (self.totalTimeTemp == -1) {
                      clearInterval(self.timeLine);
                      self.timeLine = null;
                      that.setDisable(false);
                      var linkFor = lg.Cache.Views[that._option.parentName].field[that._option.linkFor];
                      if(!linkFor.getSelfIsValided()&&linkFor._option.keyup){
                          self.init();
                          self.getVerificationButton().val((typeof self._option.postfix!='string')?'获取验证码':'获取');
                          
                      }else{
  
                          self.init();
                          self.getVerificationButton().removeClass('btn_disabled').val((typeof self._option.postfix!='string')?'获取验证码':'获取');
                      }
                      (typeof cb === 'function') && cb();
                      //self.getVerificationButton().removeClass('btn_disabled').val((typeof self._option.postfix!='string')?'获取验证码':'获取');
                     // self.getVerificationButton().
                      //self.count--;
                  }
              }, 1000);
          } 
          /*else if (that.count == 0) {
              console.log(that);
              //window.localStorage.getItem('')
              that.showMessage({message:that._option.totalTips||"已经达到限定次数"})
          }*/
      }
      return control;
  });
  
  lg.Widgets.Controls.Extend("Password", function(controlType) {
      var _shieldChar;
      var control = function(options) {
          lg.Widgets.BaseControl.call(this, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      return control;
  });
  
  lg.Widgets.Controls.Extend("RepeatPassword", function(controlType) {
      var _shieldChar;
      var control = function(options) {
          lg.Widgets.BaseControl.call(this, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      return control;
  });
  
  lg.Widgets.Controls.Extend("Email", function(controlType) {
      var _shieldChar;
      var control = function(options) {
          lg.Widgets.BaseControl.call(this, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      return control;
  });
  
  
  lg.Widgets.Controls.Extend("VerifyCode", function(controlType) {
      var _shieldChar;
      var control = function(options) {
          lg.Widgets.BaseControl.call(this, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      control.prototype.init = function() {
          //ar url = this.getVerifyCodeUrl();
          //this.getVerifyCodeImg().attr("src", url);
          this.getVerifyCodeReflashButton().on('click', {
              control: this
          }, function(e) {
              var $parent = e.data.control._element;
              var url = e.data.control.getVerifyCodeUrl();
              var img = $('<img alt="点击重试" class="yzm" width="98" height="40" />');
              if(e.data.type=='init'){
                  
                  if(e.data.control.getVerifyCodeImg().attr("src")){
                      return;
                  }else{
                      img.attr('src',url);
                      $parent.find('img').remove();
                      $parent.find('input').after(img);
                  }//?'':img.attr('src',url);
              }else{          
                  img.attr('src',url);
                  $parent.find('img').remove();
                  $parent.find('input').after(img);
              }
              
              //e.data.control.getVerifyCodeImg().attr("src", url);
          });
      }
      control.prototype.getVerifyCode = function() {
          this.getVerifyCodeReflashButton().trigger('click',{
              control: this,
              type:'init'
          });
      }
      control.prototype.getFrom = function() {
          return this._option.from || 'register';
      }
      control.prototype.getVerifyCodeUrl = function() {
          var url = this._option.url + '?from=' + this.getFrom() + '&refresh=' + new Date().getTime();
          return url;
      }
      control.prototype.getVerifyCodeReflashButton = function() {
          return this.getElement().find('a');
      }
      control.prototype.getVerifyCodeInput = function() {
          return this.getElement().find('input');
      }
      control.prototype.getVerifyCodeImg = function() {
          return this.getElement().find('img');
      }
      return control;
  });
  
  
  lg.Widgets.Controls.Extend("Switch", function(controlType) {
      var _shieldChar;
      var control = function(options) {
          lg.Widgets.BaseControl.call(this, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      control.prototype.getValue = function() {
      return this.getElement().find('.btn_active').attr('data-myvalue')||'';
      }
      
      return control;
  });
  lg.Widgets.Controls.Extend("CheckBox", function(controlType) {
      var _shieldChar;
      var control = function(options) {
          lg.Widgets.BaseControl.call(this, options);
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      control.prototype.getValue = function() {
          var chk_value = [];
          this.getElement().find('input[type="checkbox"]:checked').each(function() {
              chk_value.push($(this).attr("data-myvalue"));
          });
          return chk_value;
      }
      return control;
  });
  lg.Widgets.Controls.Extend("Button", function(controlType) {
      var _shieldChar;
      var control = function(options) {
          lg.Widgets.BaseControl.call(this, options);
          this._isValueField = false;
      };
      control.prototype = new lg.Widgets.BaseControl();
      control.prototype.controlType = controlType;
      control.prototype.init = function() {
          this.isActive = false;
          this.getElement().find('[type="button"]').on('click', {
              control: this
          }, function(e) {
              var that = e.data.control;
              that.isActive = true;
              that._option.click.call(this, {
                      control: that,
                      parent: lg.Cache.Views[that._option.parentName]
                  })
  
                  //console.log(lg.Cache.Views[that._option.parentName].CollectData());
          });
      }
      return control;
  });
  //------------------------------------------------------------------  end
  
  
  
  
  /**-----------------------------------------------------------------  start
   * 命名控件 - 视图
   */
  
  lg.Views = lg.Views || {};
  
  lg.Views.BaseView = function(options) {
      this._name = '';
      this._children = [];
      this._Validation = {};
      this._options = {};
      this.childrenData = {};
      this.field = {};
      if (options) {
          this._name = options.name;
      }
      $.extend(this._options, options);
      this._element = typeof options.name == 'string' ? $('[data-view="' + this._name + '"]') : this._name;
      lg.Cache.Views[this._name] = this;
      this.init();
  }
  lg.Views.BaseView.prototype.getElement = function() {
      return this._element;
  }
  lg.Views.BaseView.prototype.setClear = function(){
      for (var item in this.field) {
          this.field[item].setClear();
      }
  }
  lg.Views.BaseView.prototype.ValidatForm = function() {
  
      for (var item in this.field) {
          var temp = {};
          var i = {};
          if(this.field[item].getIsValueField()){
              this.field[item]._isDirty=true;
              i = this.field[item].getIsValid(this.field[item].getValue());
          }
          if (lg.Utils.isNullObject(i)) {
              this._Validation[item] = i;
          } else {
              delete this._Validation[item];
          }
          //?(delete this._Validation[item]):this._Validation[item]=i;
  
      }
      if (lg.Utils.isNullObject(this._Validation)) {
          for (var item in this._Validation) {
              this.field[item].setValidMessage(this._Validation[item],'CollectData')
          }
          return false;
      }
      return true;
  }
  lg.Views.BaseView.prototype.CollectData = function(val) {
      this.childrenData.isValidate = true;
      if(!val){
           this.childrenData.isValidate = this.ValidatForm();
      }
      
      for (var item in this.field) {
          if(this.field[item].getIsValueField()){
              this.childrenData[item] = this.field[item] ? this.field[item].getValue() : '';
          }
      }
      return this.childrenData;
  }
  lg.Views.BaseView.prototype.init = function() {
      this._options;
      this._options.fields ? this.initControls(this._options.fields) : '';
  }
  lg.Views.BaseView.prototype.initControls = function(fields) {
      for (var i = 0, len = fields.length; i < len; i++) {
          fields[i].parentName = this._name;
          this.field[fields[i].name] = new lg.Widgets.Controls[fields[i].controlType](fields[i]);
          this.field[fields[i].name].BaseInit()
              //typeof this.field[fields[i].name].init == "function"?this.field[fields[i].name].init():'';
      }
  }
  lg.Views.BaseView.prototype.extend = function(name, func) {
      this[name] = func;
  }
  
  //------------------------------------------------------------------  end
  
  
  
  
  
  /**-----------------------------------------------------------------  start
   * 命名控件 - 模型
   */
  
  lg.Models = lg.Models || {};
  
  lg.Models.BaseViewModel = function(viewName, options) {
      if (viewName) {
          this._name = viewName;
      }
      this._name = '';
      $.extend(this._options, options);
  }
  
  
  
  //------------------------------------------------------------------  end
  
  
  module.exports = lg;

});
/*!common/widgets/passport/modules/country-code/main.js*/
;define('common/widgets/passport/modules/country-code/main', ['require', 'exports', 'module'], function (require, exports, module) {


    var firstIndex = 0;
    var topPX = 0;
    var succCode = 1;

    /**
         * [hasClassWithAllParents 检测该jq对象或其父对象是否包含指定class]
         * @param  {[type]}  $target    [jq对象]
         * @param  {[type]}  checkClass [className]
         * @return {Boolean}            [description]
         */
    function hasClassWithAllParents($target, checkClass) {
        var $parent = $target;

        while ($parent[firstIndex]) {
            if ($parent.hasClass(checkClass)) return true;
            $parent = $parent.parent();
        }
        return false;
    }

    /** ***********************************国家区号选择Start*************************************/
    var $codeList = $('.area_code_list');
    var $areaCode = $('.area_code');
    $(document).on('click', '.area_code', function () {
        if ($codeList.is(':visible')) {
            $(this).removeClass('active');
            $codeList.hide();
        } else {
            $(this).addClass('active');
            $codeList.show().scrollTop(topPX);
        }
        return false;
    });
    $(document).on('click', '.area_code_list dd', function () {
        var $this = $(this);
        var $areaCode = $this.parents(".area_code_list").prev();
        $areaCode.text($this.children('span').text());
        $areaCode.trigger('click');
        return false;
    });
    $(document).on('click', function (event) {
        var $target = $(event.target);
        if (hasClassWithAllParents($target, 'area_code_list')) {
            return false;
        } else {
            $areaCode.removeClass('active');
            $codeList.hide();
        }
    });


    /** ***********************************国家区号选择End*************************************/

    $.lgAjax({
        url: GLOBAL_DOMAIN.pctx + '/register/getPhoneCountryCode.json',
        dataType: 'jsonp',
        jsonp: 'jsoncallback',
        success: function (result) {
            var listHtml = '',
                data = result.content.rows;
            // 默认选中第一项
            $areaCode.text(data[firstIndex].countryList[firstIndex].code);
            if (result.state === succCode && data) {
                for (var j = firstIndex, jLength = data.length; j < jLength; j++) {
                    listHtml += '<dt>' + data[j].name + '</dt>';
                    for (var i = firstIndex, len = data[j].countryList.length; i < len; i++) {
                        listHtml += '<dd>' + data[j].countryList[i].name + '<span>' + data[j].countryList[i].code + '</span></dd>';
                    }
                }
            } else {
                listHtml = '请求出错';
            }
            
            $('.code_list_main').append(listHtml);
        }
    });

    module.exports = function() {
        var val = $(".area_code_list dd").eq(0).find("span").text();
        $('.area_code').text(val).removeClass('active');
        $codeList.hide();
    }
    

});

/*!common/widgets/passport/utils/index.js*/
;define('common/widgets/passport/utils/index', ['require', 'exports', 'module'], function (require, exports, module) {
    /**
     * 工具集
     * @type {Object}
     */

    var VERSION = "0.0.1";

    var IFRAMEINDEX = 0;


    var DEBUG = false;

    /*
    * url正则匹配
    * @type {RegExp}
    */
   var REGEXPURL = /^(https?):\/\/((?:[\u4E00-\u9FA5a-z0-9.-]|%[0-9A-F]{2}){2,})(?::(\d+))?((?:\/(?:[a-z0-9-._~!$&'()*+,;=:@]|%[0-9A-F]{2})*)*)(?:\?((?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*))?(?:#((?:[a-z0-9-._~!$&'()*+,;=:\/?@]|%[0-9A-F]{2})*))?$/i;

    function analyzeUri(config) {

        var loc = top.location;
        var origin = {
            protocol: loc.protocol.substring(0, loc.protocol.length - 1),
            hostname: loc.hostname,
            port: loc.port || '80' // 默认80端口
        };

        var targetMatches = REGEXPURL.exec(config.url);

        // 不为null，则说明有匹配【需要判断是否跨域】
        // 如果为null，则说明是不加域名的绝对地址请求，例如：'/a/c.json'【不用跨域】
        if (targetMatches && targetMatches.length) {
            var target = {
                protocol: targetMatches[1],
                hostname: targetMatches[2],
                port: targetMatches[3] || '80'
            };

            // 如果跨域
            if (origin.protocol != target.protocol || origin.hostname != target.hostname || origin.port != target.port) {
                config.dataType = 'jsonp';
                config.jsonp = 'jsoncallback';
            }
        }

    }

    var Iframes = {
        getUniqueIndex: function() {
            return ++IFRAMEINDEX
        },
        createIframe: function (type, encodeUrl, id) {
                var iframe = '<iframe src="' + encodeUrl + '" id="' + type + '_' + id + '" style="display:none;"></iframe>';
                $('body').append(iframe);        
        },
        delIframe: function(type, index) {
            var id = type + '_' + index;
            $('#' + id).remove();
            util.tinfo('Iframe ' + id + ' removed');
        }
    }


    var util = {
        iframe: Iframes,

        /**
         * 跨系统调用[jsonp]
         *
         * @param {Object} opt 请求参数
         *
         * @param {string} opt.url 请求路径
         * @param {string} opt.type optional 请求方法 'GET/POST'，默认'POST'
         * @param {Object} opt.params 请求参数
         * @param {Function} opt.succ 成功
         * @param {Function} opt.fail 失败
         */
        rpc: function (opt) {

            if (!opt.url)
                return;

            opt.type || (opt.type = 'POST');
            opt.params || (opt.params = {});

            var me = arguments.callee;

            util.tinfo('Start passport.rpc: ' + opt.url);

            var config = {

                type: opt.type,
                data: opt.params,
                url: opt.url,
                dataType: 'json'/*,
                                                        jsonp: 'jsoncallback'*/

            };

            // 分析url是否跨域
            analyzeUri(config);

            $.lgAjax(config).done(function (result, textStatus, jqXHR) {

                util.tinfo('passport.rpc.succ: ' + textStatus);

                // 判断是不是跨系统，且未登录
                if (result.state == '10001') {
                    var crossServiceUrl = result.content.data.crossServiceUrl.replace(/^https?\:/i, window.location.protocol); // 兼容 http/https

                    PASSPORT.remote(
                        crossServiceUrl,
                        // 成功
                        function (data) {
                            util.tinfo('passport.rpc.remote.succ');
                            me(opt);
                        },
                        // 失败
                        function (data) {
                            util.tinfo('passport.rpc.remote.fail');
                            opt.fail && opt.fail.apply(null, [data]);
                        }
                    );

                    return;
                }

                // 如果跨系统已经登录，则正常响应
                opt.succ && opt.succ.apply(null, arguments);

            }).fail(function (jqXHR, textStatus, errorThrown) {
                util.tinfo('passport.rpc.fail: ' + textStatus);
                opt.fail && opt.fail.apply(null, arguments);
            });

        },

        /**
         * 得到默认的请求url
         *
         * @param  {string} url    url
         * @param  {Object} params 参数
         */
        getTargetUrl: function (url, params) {

            var pas = {
                fl: (params.fl != undefined ? params.fl : true),
                service: params.service,
                osc: params.osc,
                ofc: params.ofc,
                pfurl: document.URL
            };

            return url + '?' + $.param(pas);

        },

        //得到当前页面的url
        getCurEncodeUrl: function () {
            return encodeURIComponent(document.URL);
        },

        // //创建iframe
        // createIframe: function (id, encodeUrl, selfId) {
        //     var iframe = '<iframe src="' + encodeUrl
        //         // + '" id="' + id
        //         // 每一个iframe要区分自己
        //         + '" id="' + id + '_' + (selfId || IFRAMEINDEX) + '" style="display:none;"></iframe>';
        //     $('body').append(iframe);

        //     // 当前构建完毕要自加
        //     IFRAMEINDEX++;
        // },

        // 请求器
        requester: function (params, callback) {
            params.dataType = params.dataType || 'json';
            params.type = params.type || 'POST';
            params.data = params.data || {};
            $.lgAjax(params).done(function (response) {
                callback && callback(response);
            });
        },

        /**
         * 简易字符串格式化
         */
        strFormat: function (source, opts) {
            source = String(source);
            var data = Array.prototype.slice.call(arguments, 1),
                toString = Object.prototype.toString;
            if (data.length) {
                data = data.length == 1 ?
                    /* ie 下 Object.prototype.toString.call(null) == '[object Object]' */
                    (opts !== null && (/\[object Array\]|\[object Object\]/.test(toString.call(opts))) ? opts : data) : data;
                return source.replace(/#\{(.+?)\}/g, function (match, key) {
                    var replacer = data[key];
                    // chrome 下 typeof /a/ == 'function'
                    if ('[object Function]' == toString.call(replacer)) {
                        replacer = replacer(key);
                    }
                    return ('undefined' == typeof replacer ? '' : replacer);
                });
            }
            return source;
        },

        /**
         * 日志头设置
         * @type {String}
         */
        tipheader: 'Lagou Passport v' + VERSION + ' -> ',

        /**
         * 展示日志
         */
        tip: function () {
            if (!DEBUG)
                return;
            var method = arguments[0];
            var args = Array.prototype.slice.call(arguments, 1);
            console[method].apply(console, args);
        },

        tinfo: function (msg) {
            util.tip('info', util.tipheader + msg);
        }

    };

    module.exports = util;
});



/*!common/widgets/passport/modules/login/main.js*/
;define('common/widgets/passport/modules/login/main', ['require', 'exports', 'module', 'common/components/util/htoc', "common/widgets/passport/common/js/sense", "common/widgets/passport/modules/wechat-qrcode/main", "common/components/modal/modal", "common/widgets/passport/common/js/lagou", "common/widgets/passport/modules/country-code/main", "common/widgets/passport/utils/index"], function (require, exports, module) {
    var inpututil = require('common/components/util/htoc');
    var initSense = require("common/widgets/passport/common/js/sense");
    var QrCode = require("common/widgets/passport/modules/wechat-qrcode/main");
    require("common/components/modal/modal");
    var lg = require("common/widgets/passport/common/js/lagou");
    var restContryCode = require("common/widgets/passport/modules/country-code/main");
    var util = require("common/widgets/passport/utils/index");

    var qrCode = new QrCode({
        wrapper: ".login-pop",
        isLogin: true
    });

    var verifyStyle;
    var isNoLagou;
    var sense;
    var voiceTimer = null;

    var stateList = {
        1: {
            message: "成功",
            linkFor: "username",
            level: "info"
        },
        210: {
            message: "请输入有效的手机/邮箱",
            linkFor: "username",
            level: "error"
        },
        211: {
            message: "请输入6-16位密码，字母区分大小写",
            linkFor: "password",
            level: "error"
        },
        220: {
            message: "请输入已验证手机/邮箱",
            linkFor: "username",
            level: "error"
        },
        241: {
            message: "请输入密码",
            linkFor: "password",
            level: "error"
        },
        400: {
            message: "账号和密码不匹配",
            linkFor: "password",
            level: "error"
        },
        10010: {
            message: "图形验证码不正确",
            linkFor: "request_form_verifyCode",
            level: "error"
        },
        10011: {
            message: "登录错误次数过多，请稍后再试或<a href='https://passport.lagou.com/accountPwd/toReset.html'>重置密码</a>",
            linkFor: "password",
            level: "error"
        },
        10012: {
            message: "操作过于频繁，请联系管理员",
            linkFor: "password",
            level: "error"
        }
    };

    var phoneCodeStateList = {
        1:{message:"验证码已发送，请查收短信",linkFor:"phoneVerificationCode",level:"info"},
        201:{message:"请输入手机号码",linkFor:"username",level:"error"},
        203:{message:"输入号码与归属地不匹配",linkFor:"username",level:"error"},
        204:{message:"系统错误",linkFor:"phoneVerificationCode",level:"error"},
        205:{message:"输入号码与归属地不匹配",linkFor:"username",level:"error"},
        206:{message:"系统错误",linkFor:"phoneVerificationCode",level:"error"},
        207:{message:"该手机获取验证码已达上限，请明天再试",linkFor:"phoneVerificationCode",level:"error"},
        208:{message:"验证码发送太过频繁，请稍后再试",linkFor:"phoneVerificationCode",level:"error"},
        209:{message:"该手机已被注册，请重新输入或直接登录",linkFor:"username",level:"error"},
        222:{message:"该手机号未注册",linkFor:"username",level:"error"},
        304:{message:"用户未登录",linkFor:"username",level:"error"},
        402:{message:"获取验证码超时，请稍后再试",linkFor:"phoneVerificationCode",level:"error"},
        10010:{message:"图形验证码不正确",linkFor:"request_form_verifyCode",level:"error"},
        10011:{message:"操作过于频繁，请联系管理员",linkFor:"phoneVerificationCode",level:"error"},
        10012:{message:"操作过于频繁，请联系管理员",linkFor:"phoneVerificationCode",level:"error"}
    };

    var passwordView = new lg.Views.BaseView({
        name: "passwordLogin",
        fields: [{
            name: "username",
            validRules: [{
                    mode: "require",
                    data: "",
                    message: "请输入已验证手机/邮箱",
                    trigger: "blur"
                }, {
                    mode: "pattern",
                    isUse: true,
                    status: false,
                    data: {
                        // phone: /^(0|86|17951)?((13[0-9]|15[012356789]|17[0135678]|18[0-9]|14[57])[0-9]{8})$/,
                        phone: /^\d{5,15}$/,
                        email: /^((([a-z]|\d|[!#\$%&"\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&"\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i
                    },
                    message: "请输入有效的手机/邮箱"
                }

            ],
            controlType: "Phone"
        }, {
            name: "password",
            validRules: [{
                mode: "require",
                data: "",
                message: "请输入密码"
            }, {
                mode: "pattern",
                data: "/^[\\S\\s]{6,16}$/",
                message: "请输入6-16位密码，字母区分大小写"
            }],
            controlType: "Password"
        }, {
            name: "request_form_verifyCode",
            isVisible: false,
            validRules: [],
            from: "register",
            url: "https://passport.lagou.com/vcode/create",
            controlType: "VerifyCode"
        }]
    });

    // 全角转半角
    $('.HtoC_JS').each(function () {
        $(this).keyup(function() {
            inpututil.HtoC($(this))
        })
    })

    $(".input_border input").focus(function () {
        $(this).parents('.input_border').attr('class', 'input_border focus')
    })
    $(".input_border input").blur(function () {
        $(this).parents('.input_border').attr('class', 'input_border')
    })
    $(".login_enter_password").keydown(function (event) {
        if(event.keyCode === 13) {
            window.LGWebTj && window.LGWebTj({
                _lt: 'pcclick',
                _address_id: '1m2g',
                added_props: {
                    'action_type': 'enter',
                    'tjEncodeId': '1m2g',
                    'tjNo': '0003'
                }
            });
            if (!verifyStyle) {
                console.log("初始化中 请稍后");
                return;
            }
            if (isNoLagou) {
                if (!sense) {
                    return;
                }
                if (!passwordView.ValidatForm()) {
                    return;
                }
                sense._c_interactive = 2;
                sense._c_onSuccess = function(data) {
                    passWordSubmit(data.challenge);
                }
                sense.sense();
            } else {
                passWordSubmit();
            }
        }
    })
    $(".login-btn.login-password").bind("click", function() {
        if (!verifyStyle) {
            console.log("初始化中 请稍后");
            return;
        }
        if (isNoLagou) {
            if (!sense) {
                return;
            }
            if (!passwordView.ValidatForm()) {
                return;
            }
            sense._c_interactive = 2;
            sense._c_onSuccess = function(data) {
                passWordSubmit(data.challenge);
            }
            sense.sense();
        } else {
            passWordSubmit();
        }
    });

    var passWordSubmitFlag = false;
    function passWordSubmit(challenge) {
        if (passWordSubmitFlag) {
            return;
        }
        passWordSubmitFlag = true;
        var that = {
            // control: passwordView.field["submit"],
            parent: passwordView
        }
        var params = that.parent.CollectData();
        var SALT = "veenike";
        if (params.isValidate) {
            challenge && (params.challenge = challenge);
            params.password = md5(params.password);
            params.password = md5(SALT + params.password + SALT);

            $.lgAjax({
                data: params,
                url: GLOBAL_DOMAIN.pctx + "/login/login.json",
                dataType: "jsonp",
                jsonp: "jsoncallback"
            }).done(function(result) {

                stateList[210].message = "请输入有效的手机/邮箱";
                stateList[400].message = "账号和密码不匹配";
                stateList[400].linkFor = "password";

                if (result.state == 1) {
                    var index = util.iframe.getUniqueIndex();
                    var turl = util.getTargetUrl(GLOBAL_DOMAIN.pctx + "/ajaxLogin/frameGrant.html", {
                        fl: "2",
                        service: document.URL,
                        osc: "PASSPORT._pscb(" + index + ")",
                        ofc: "PASSPORT._pfcb(" + index + ")"
                    });
                    util.iframe.createIframe("popup_login_iframe", turl, index);

                } else {
                    if (result.state == 10010) {
                        that.parent.field["request_form_verifyCode"].getVerifyCode();
                        that.parent.field["request_form_verifyCode"].setVisible(true);
                    }
                    if (stateList[result.state]) {
                        that.parent.field[stateList[result.state].linkFor].showMessage({
                            message: stateList[result.state].message
                        });
                    } else {
                        that.parent.field["password"].showMessage({
                            message: result.message
                        });
                    }
                    passWordSubmitFlag = false;
                }

            }).fail(function() {
                passWordSubmitFlag = false;
            })
        }
    }
    //获取验证码
    passwordView.field["request_form_verifyCode"].getVerifyCode();


    var codeView = new lg.Views.BaseView({
        name: "codeLogin",
        fields: [{
            name: "username",
            validRules: [{
                    mode: "require",
                    data: "",
                    message: "请输入已验证手机",
                    trigger: "blur"
                }, {
                    mode: "pattern",
                    isUse: true,
                    status: false,
                    data: {
                        phone: /^\d{5,11}$/
                    },
                    message: "请输入有效的手机"
                }

            ],
            controlType: "Phone"
        }, {
            name: "request_form_verifyCode",
            isVisible: !isNoLagou,
            validRules: [{
                mode: "require",
                data: "",
                message: "请输入验证码"
            }, {
                mode: "pattern",
                data: "/^[a-zA-Z0-9\u4e00-\u9fa5]{4,4}$/",
                message: "请输入正确的验证码"
            }],
            from: "register",
            url: "https://passport.lagou.com/vcode/create",
            controlType: "VerifyCode"
        }, {
            name: "phoneVerificationCode",
            linkFor: "username",
            verifyCode: "request_form_verifyCode",
            totalTips: "该手机获取验证码已达上限，请明天再试",
            validRules: [{
                    mode: "require",
                    data: "",
                    message: "请输入6位数字验证码"
                }, {
                    mode: "pattern",
                    isUse: true,
                    status: false,
                    data: "/^[0-9]{6,6}$/",
                    message: "请输入6位数字验证码"
                }

            ],
            url: GLOBAL_DOMAIN.pctx + "/login/sendLoginVerifyCode.json",
            controlType: "PhoneVerificationCode",
            click: function(e) {
                if (!verifyStyle) {
                    console.log("初始化中 请稍后");
                    return;
                }
                if (isNoLagou) {
                    if (!sense) {
                        return;
                    }
                    sense._c_interactive = 3;
                    sense._c_onSuccess = function(data) {
                        getVerifyCode(e, data.challenge);
                    }
                    sense._c_onClose = function() {
                        e.control.setDisable(false);
                        e.control.init();
                    }
                    sense.sense();
                } else {
                    getVerifyCode(e);
                }
            }
        }, {
            name: "autoPhoneVerificationCode",
            linkFor: "username",
            verifyCode: "request_form_verifyCode",
            validRules: [],
            url: GLOBAL_DOMAIN.pctx  + "/login/sendLoginVerifyCode.json",
            controlType: "PhoneVerificationCode",
            click: function(e) {
                if (!verifyStyle) {
                    console.log("初始化中 请稍后");
                    return;
                }
                if (isNoLagou) {
                    if (!sense) {
                        return;
                    }
                    sense._c_interactive = 3;
                    sense._c_onSuccess = function(data) {
                        getAutoVerifyCode(e, data.challenge);
                    }
                    sense._c_onClose = function() {
                        e.control.setDisable(false);
                        e.control.init();
                    }
                    sense.sense();
                } else {
                    getAutoVerifyCode(e);
                }
            }
        }, {
            name: "submit",
            validRules: [],
            controlType: "Button",
            click: function(e) {

            }
        }]
    });

    $(".login_enter_code").keydown(function (event) {
        if(event.keyCode === 13) {
            window.LGWebTj && window.LGWebTj({
                _lt: 'pcclick',
                _address_id: '1m2g',
                added_props: {
                    'action_type': 'enter',
                    'tjEncodeId': '1m2g',
                    'tjNo': '0003'
                }
            });
            if (!verifyStyle) {
                console.log("初始化中 请稍后");
                return;
            }
            if (isNoLagou) {
                if (!sense) {
                    return;
                }
                codeViewSubmit(111);
            } else {
                codeViewSubmit();
            }
        }
    })

    $(".login-btn.login-code").bind("click", function() {
        if (!verifyStyle) {
            console.log("初始化中 请稍后");
            return;
        }
        if (isNoLagou) {
            if (!sense) {
                return;
            }
            codeViewSubmit(111);
        } else {
            codeViewSubmit();
        }
    });

    function getVerifyCode(e, challenge) {
        var that = e;
        if (that.control.totalTimeTemp == -1 || that.control.totalTimeTemp == that.control.getTopTime()) {
            $.lgAjax({
                url: that.control._option.url,
                data: {
                    challenge: challenge,
                    countryCode: $("[data-view='codeLogin'] .area_code").text(),
                    phone: that.linkFor.getValue(),
                    type: 0,
                    request_form_verifyCode: lg.Cache.Views[that.control._option.parentName].field["request_form_verifyCode"].getValue()
                },
                dataType: "jsonp",
                jsonp: "jsoncallback",
                cache: false
            }).done(function(result) {
                var $verifyInputParent;
                e.control.setDisable(false);
                //提示信息
                if (phoneCodeStateList[result.state]) {
                    that.parent.field[phoneCodeStateList[result.state].linkFor].showMessage({
                        message: phoneCodeStateList[result.state].message
                    });
                }
                //成功
                if (result.state == 1) {
                    $verifyInputParent = $(".login-pop .passport-pop-wrapper.account [data-propertyname='phoneVerificationCode']");
                    //语音验证隐藏
                    $(".verify_tips_main").hide();
                    e.control.starttime(e.control, function() {

                        //倒计时结束回调函数
                        $(".login-pop .passport-pop-wrapper.account .auto_phone").val("语音验证");
                        $(".login-pop .passport-pop-wrapper.account .verify_tips_main").show();
                        $verifyInputParent.find(".first_child").removeClass("input_warning");
                        $verifyInputParent.children(".input_tips").remove();
                    });
                    return;
                } else {
                    e.control.init();
                    that.parent.field["request_form_verifyCode"].getVerifyCode();
                }

            });
        }
    }

    function getAutoVerifyCode(e, challenge) {
        var that = e;
        if (that.control.totalTimeTemp == -1 || that.control.totalTimeTemp == that.control.getTopTime()) {

            $.lgAjax({
                url: that.control._option.url,
                data: {
                    countryCode: $("[data-view='codeLogin'] .area_code").text(),
                    phone: that.linkFor.getValue(),
                    type: 1,
                    request_form_verifyCode: lg.Cache.Views[that.control._option.parentName].field["request_form_verifyCode"].getValue(),
                    challenge: challenge
                },
                dataType: "jsonp",
                jsonp: "jsoncallback",
                cache: false
            }).done(function(result) {
                var stateData = phoneCodeStateList[result.state],
                    count = that.control.getTopTime(),
                    $verifyInputParent;
                if (result.state === 1) {
                    $verifyInputParent = $(".login-pop .passport-pop-wrapper.account [data-propertyname='phoneVerificationCode']");
                    $verifyInputParent.find(".last_child").addClass("btn_disabled").prop("disabled", true);
                    clearInterval(voiceTimer);
                    voiceTimer = setInterval(function() {
                        //语音验证重新激活
                        if (--count < 0) {
                            clearInterval(voiceTimer);

                            //更新短信验证码状态
                            $verifyInputParent.find(".first_child").removeClass("input_warning");
                            $verifyInputParent.find(".last_child").removeClass("btn_disabled").removeProp("disabled");

                            //显示语音验证码
                            $(".login-pop .auto_phone").removeProp("disabled");
                            $(".login-pop .verify_tips_count_down").hide();
                            $(".login-pop .verify_tips_main").show();
                            e.control.init();
                            //语音验证已发送
                        } else {
                            if (count === that.control.getTopTime() - 1) {
                                $(".login-pop .verify_tips_main").hide();
                            }
                            $(".login-pop .verify_tips_count_down").html("请留意接收手机来电，" + count + "秒后可重试…").show();
                        }
                    }, 1000);
                } else {
                    e.control.init();
                    if (stateData) {
                        that.parent.field[stateData.linkFor].showMessage({
                            message: stateData.message
                        });
                    }
                    that.parent.field["request_form_verifyCode"].getVerifyCode();
                }

                e.control.setDisable(false);

            });
        }

    }

    var codeViewSubmitFlag = false;
    function codeViewSubmit(challenge) {
        if (codeViewSubmitFlag) {
            return;
        }
        codeViewSubmitFlag = true;
        var that = {
            parent: codeView
        }
        var params = that.parent.CollectData();
        params.countryCode = $(".login-pop [data-view='codeLogin'] .area_code").text();
        challenge && (params.challenge = challenge);
        if (params.isValidate) {
            $.lgAjax({
                url: GLOBAL_DOMAIN.pctx + "/login/login.json",
                data: params,
                dataType: "jsonp",
                jsonp: "jsoncallback",
                cache: false
            }).done(function(result) {

                stateList[210].message = "输入号码与归属地不匹配";
                stateList[400].message = "账号和验证码不匹配";
                stateList[400].linkFor = "phoneVerificationCode";

                if (result.state == 1) {
                    var index = util.iframe.getUniqueIndex();
                    var turl = util.getTargetUrl(GLOBAL_DOMAIN.pctx + "/ajaxLogin/frameGrant.html", {
                        fl: "2",
                        service: document.URL,
                        osc: "PASSPORT._pscb(" + index + ")",
                        ofc: "PASSPORT._pfcb(" + index + ")"
                    });
                    util.iframe.createIframe("popup_login_iframe", turl, index);
                } else {
                    if (result.state == 10010) {
                        that.parent.field["request_form_verifyCode"].getVerifyCode();
                        that.parent.field["request_form_verifyCode"].setVisible(true);
                    }
                    if (stateList[result.state]) {
                        that.parent.field[stateList[result.state].linkFor].showMessage({
                            message: stateList[result.state].message
                        });
                    } else {
                        that.parent.field["phoneVerificationCode"].showMessage({
                            message: result.message
                        });
                    }
                    that.parent.field["request_form_verifyCode"].getVerifyCode();
                    codeViewSubmitFlag = false;
                }

            }).fail(function() {
                codeViewSubmitFlag = false;
            })
        }
    }


    $(".forms-bottom-code .change-login-type").bind("click", function() {
        changeLoginType("password");
    });

    $(".forms-bottom-password .change-login-type").bind("click", function() {
        changeLoginType("code");
    });


    function changeLoginType(type) {
        if (type === "code") {
            $(".login-pop .forms-area").removeClass("password");
            $(".login-pop .passport-pop-wrapper.wechat .change-btn").removeClass("password");
            return;
        }
        if (type === "password") {
            $(".login-pop .forms-area").addClass("password");
            $(".login-pop .passport-pop-wrapper.wechat .change-btn").addClass("password");
            return;
        }
    }

    $(".login-pop  .account .change-btn").bind("click", function() {
        $(".login-pop .passport-pop-wrapper.wechat").fadeIn();
        qrCode.openQrCode();
    });
    $(".login-pop .wechat .change-btn").bind("click", function() {
        $(".login-pop .passport-pop-wrapper.wechat").fadeOut();
        qrCode.closeQrCode();
    });

    $(".register-btn").bind("click", function() {
        $(".login-pop").modal("hide");
        PASSPORT.registerPopup();
    });

    $(".login-pop .close").bind("click", function() {
        qrCode.closeQrCode();
    });

    initSense(function(_sense) {
        sense = _sense;
        verifyStyle = "nolagou";
        isNoLagou = true;
        codeView && codeView.field["request_form_verifyCode"].setVisible(false);
    }, function() {
        verifyStyle = "lagou";
        isNoLagou = false;
        codeView && codeView.field["request_form_verifyCode"].setVisible(true);
        codeView && codeView.field["request_form_verifyCode"].getVerifyCode();
    });

    module.exports = function() {
        $(".login-pop .passport-pop-wrapper.wechat").hide();
        changeLoginType("password");
        clearInterval(voiceTimer);
        passwordView.setClear();
        codeView.setClear();
        restContryCode();
        $(".verify_tips_main").hide();
        $(".verify_tips_count_down").hide();
        $(".login-pop").modal("show");
    }


});


/*!common/widgets/passport/modules/register/main.js*/
;define('common/widgets/passport/modules/register/main', ['require', 'exports', 'module', 'common/components/util/htoc', "common/widgets/passport/common/js/sense", "common/widgets/passport/modules/wechat-qrcode/main", "common/components/modal/modal", "common/widgets/passport/common/js/lagou", "common/widgets/passport/modules/country-code/main"], function (require, exports, module) {
    var util = require('common/components/util/htoc');
    var initSense = require("common/widgets/passport/common/js/sense");
    var QrCode = require("common/widgets/passport/modules/wechat-qrcode/main");
    require("common/components/modal/modal");
    var lg = require("common/widgets/passport/common/js/lagou");
    var restContryCode = require("common/widgets/passport/modules/country-code/main");
    var errVerifyCode = 10010;
    var senseErrorCode = 21010;
    var registerFlag = false;
    var verifySenseChallenge = 111;
    var timer;
    var qrCode = new QrCode({
        wrapper: ".register-pop",
        isLogin: false
    });
    var succCode = 1;
    var firstIndex = 0;
    var phoneCodeStateList = {
        1: {message: "验证码已发送，请查收短信", linkFor: 'phoneVerificationCode', level: 'info'},
        201: {message: "请输入手机号码", linkFor: 'phone', level: 'error'},
        203: {message: "输入号码与归属地不匹配", linkFor: 'phone', level: 'error'},
        204: {message: "系统错误", linkFor: 'phoneVerificationCode', level: 'error'},
        205: {message: "输入号码与归属地不匹配", linkFor: 'phone', level: 'error'},
        206: {message: "系统错误", linkFor: 'phoneVerificationCode', level: 'error'},
        208: {message: "验证码发送太过频繁，请稍后再试", linkFor: 'phoneVerificationCode', level: 'error'},
        209: {message: "该手机已被注册，请重新输入或直接登录", linkFor: 'phone', level: 'error'},
        220: {message: "输入号码与归属地不匹配", linkFor: 'phone', level: 'error'},
        222: {message: "该手机号未注册", linkFor: 'phone', level: 'error'},
        304: {message: "用户未登录", linkFor: 'phone', level: 'error'},
        310: {message: "该手机获取验证码已达上限，请明天再试", linkFor: 'phoneVerificationCode', level: 'error'},
        311: {message: "验证码发送太过频繁，请稍后再试", linkFor: 'phoneVerificationCode', level: 'error'},
        402: {message: "手机验证码不正确", linkFor: 'phoneVerificationCode', level: 'error'},
        10010: {message: "图形验证码不正确", linkFor: 'request_form_verifyCode', level: 'error'},
        10011: {message: "操作过于频繁，请联系管理员", linkFor: 'phoneVerificationCode', level: 'error'},
        10012: {message: "操作过于频繁，请联系管理员", linkFor: 'phoneVerificationCode', level: 'error'}
    };

    var isNoLagou;
    var sense;
    var verifyStyle;

    var fieldsModal = [{
        name: 'phone',
        validRules: [{
            mode: 'require',
            data: '',
            message: '请输入手机号码',
            trigger: 'blur'
        }, {
            mode: 'pattern',
            isUse: true,
            status: false,
            data: { phone: /^\d{5,11}$/ },
            message: '请输入正确的手机号码'
        }],
        controlType: "Phone"
    }, {
        name: 'phoneVerificationCode',
        linkFor: 'phone',
        verifyCode: 'request_form_verifyCode',
        totalTips: "该手机获取验证码已达上限，请明天再试",
        validRules: [{
            mode: 'require',
            data: '',
            message: '请输入6位数字验证码'
        }, {
            mode: 'pattern',
            isUse: true,
            status: false,
            data: '/^[0-9]{6,6}$/',
            message: '请输入6位数字验证码'
        }],
        url: '/register/getPhoneVerificationCode.json',
        controlType: "PhoneVerificationCode",
        click: function (e) {
            if (!verifyStyle) {
                console.log("初始化中 请稍后");
                return;
            }
            if (isNoLagou) {
                if (!sense) {
                    return;
                }
                sense._c_interactive = 3;
                sense._c_onSuccess = function (data) {
                    getVerifyCode(e, data.challenge);
                }
                sense._c_onClose = function () {
                    e.control.setDisable(false);
                    e.control.init();
                }
                sense.sense();
            } else {
                getVerifyCode(e);
            }
        }
    }, {
        name: 'autoPhoneVerificationCode',
        // isVisible: false,
        linkFor: 'phone',
        verifyCode: 'request_form_verifyCode',
        validRules: [],
        url: '/register/getPhoneVerificationCode.json',
        controlType: "PhoneVerificationCode",
        click: function (e) {
            if (!verifyStyle) {
                console.log("初始化中 请稍后");
                return;
            }
            if (isNoLagou) {
                if (!sense) {
                    return;
                }
                sense._c_interactive = 3;
                sense._c_onSuccess = function (data) {
                    getAutoVerifyCode(e, data.challenge);
                }
                sense._c_onClose = function () {
                    e.control.setDisable(false);
                    e.control.init();
                }
                sense.sense();
            } else {
                getAutoVerifyCode();
            }
        }
    },
    {
        name: 'request_form_verifyCode',
        isVisible: !isNoLagou,
        validRules: [{
            mode: 'require',
            data: '',
            message: '请输入验证码'
        }, {
            mode: 'pattern',
            data: '/^[a-zA-Z0-9\u4e00-\u9fa5]{4,4}$/',
            message: '请输入正确的验证码'
        }],
        from: 'register',
        url: 'https://passport.lagou.com/vcode/create',
        controlType: "VerifyCode"
    }, {
        name: 'submit',
        validRules: [],
        controlType: "Button",
        url: "/register/register.json",
        click: submit_func
    }];

    var phoneViewModelC = new lg.Views.BaseView({
        name: 'phoneRegisterC',
        fields: fieldsModal
    });

    var phoneViewModelB = new lg.Views.BaseView({
        name: 'phoneRegisterB',
        fields: fieldsModal
    });


    function getAccountType() {
        var $topWrapper = $(".register-pop .forms-top-wrapper");
        if ($topWrapper.hasClass("account-b")) {
            return "B"
        };
        return "C"
    }

    function submit_func(e) {
        var that = e;
        var $parent;
        var params = that.parent.CollectData();
        if (getAccountType() === "B") {
            $parent = $("[data-view='phoneRegisterB']");
            params.type = 1;
        } else {
            $parent = $("[data-view='phoneRegisterC']");
            params.type = 0;
        }
        if (params.isValidate) {
            if (registerFlag) {
                return;
            }
            registerFlag = true;
            if (isNoLagou) {
                verifySenseChallenge && (params.challenge = verifySenseChallenge);
            }
            params.countryCode = $parent.find('.area_code').text();
            $.lgAjax({
                url: GLOBAL_DOMAIN.pctx + "/register/register.json",
                data: params,
                dataType: "jsonp",
                jsonp: "jsoncallback",
                cache: false
            }).done(function (result) {

                var stateList = {
                    1: { message: "成功", linkFor: 'phoneVerificationCode', level: 'info' },
                    203: { message: "输入号码与归属地不匹配", linkFor: 'phone', level: 'error' },
                    209: { message: "该手机已被注册，请重新输入或直接登录", linkFor: 'phone', level: 'error' },
                    222: { message: "输入号码与归属地不匹配", linkFor: 'phone', level: 'error' },
                    240: { message: "请输入手机号码", linkFor: 'phone', level: 'error' },
                    245: { message: "请输入6位数字验证码", linkFor: 'phoneVerificationCode', level: 'error' },
                    401: { message: "手机验证码不正确", linkFor: 'phoneVerificationCode', level: 'error' },
                    402: { message: "手机验证码不正确", linkFor: 'phoneVerificationCode', level: 'error' },
                    403: { message: "系统错误", linkFor: 'phoneVerificationCode', level: 'error' },
                    500: { message: "系统错误", linkFor: 'phoneVerificationCode', level: 'error' },
                    501: { message: "系统错误", linkFor: 'phoneVerificationCode', level: 'error' },
                    502: { message: "系统错误", linkFor: 'phoneVerificationCode', level: 'error' },
                    10010: { message: "图形验证码不正确", linkFor: 'request_form_verifyCode', level: 'error' },
                    10011: { message: "操作过于频繁，请联系管理员", linkFor: 'phoneVerificationCode', level: 'error' },
                    10012: { message: "操作过于频繁，请联系管理员", linkFor: 'phoneVerificationCode', level: 'error' }
                };
                

                if (result.state === succCode) {
                    var turl = GLOBAL_DOMAIN.pctx + "/grantServiceTicket/grant.html";
                    window.location.href = turl;
                    registerFlag = true;
                } else {
                    // 显示图形验证码
                    if (result.state === errVerifyCode) {
                        that.parent.field["request_form_verifyCode"].setVisible(true);
                    }

                    if (stateList[result.state]) {
                        that.parent.field[stateList[result.state].linkFor].showMessage({ message: stateList[result.state].message });
                    } else {
                        that.parent.field['phoneVerificationCode'].showMessage({ message: result.message });
                    }
                    that.parent.field["request_form_verifyCode"].getVerifyCode();
                    registerFlag = false;
                }
                
            }).fail(function () {
                registerFlag = false;
            });
        }

    }

    function getVerifyCode(e, challenge) {
        var control;
        var phoneViewModel;
        var $parent;
        if (getAccountType() === "B") {
            control = phoneViewModelB.field['phoneVerificationCode'];
            phoneViewModel = phoneViewModelB;
            $parent = $("[data-view='phoneRegisterB']");
        } else {
            control = phoneViewModelC.field['phoneVerificationCode'];
            phoneViewModel = phoneViewModelC;
            $parent = $("[data-view='phoneRegisterC']")
        }
      
        var stopDowntimeFlag = -1;
        if (control.totalTimeTemp === stopDowntimeFlag || control.totalTimeTemp === control.getTopTime()) {
            $.lgAjax({
                url: GLOBAL_DOMAIN.pctx + "/register/getPhoneVerificationCode.json",
                data: {
                    challenge: challenge,
                    countryCode: $parent.find('.area_code').text(),
                    phone: phoneViewModel.field['phone'].getValue(),
                    type: 0,
                    request_form_verifyCode: lg.Cache.Views[control._option.parentName].field['request_form_verifyCode'].getValue()
                },
                dataType: "jsonp",
                jsonp: "jsoncallback",
                cache: false
            }).done(function (result) {
                control.setDisable(false);
                var $verifyInputParent;
                if (result.state === senseErrorCode) {
                    ajaxError(result.message);
                    return;
                }
                if (phoneCodeStateList[result.state]) {
                    phoneViewModel.field[phoneCodeStateList[result.state].linkFor].showMessage({ message: phoneCodeStateList[result.state].message });
                } else {
                    phoneViewModel.field['phoneVerificationCode'].showMessage({ message: result.message });
                }
                if (result.state === succCode) {
                    verifySenseChallenge = challenge;
                    $verifyInputParent = $parent.find('[data-propertyname="phoneVerificationCode"]');
                    // 语音验证隐藏
                    $parent.find('.verify_tips_main').hide();
                    control.starttime(control, function () {

                        // 倒计时结束回调函数
                        
                        $parent.find('.verify_tips_main').show();
                        $verifyInputParent.find('.first_child').removeClass('input_warning');
                        $verifyInputParent.children('.input_tips').remove();
                        $parent.find(".auto_phone").val("语音验证");
                    });
                } else {
                    control.init();
                    phoneViewModel.field["request_form_verifyCode"].getVerifyCode();
                }
                

            });
        }
    }

    function getAutoVerifyCode(e, challenge) {
        var that = e;
        var stopDowntimeFlag = -1;
        var $parent;
        if (getAccountType() === "B") {
            $parent = $("[data-view='phoneRegisterB']");
        } else {
            $parent = $("[data-view='phoneRegisterC']");
        }
        if (that.control.totalTimeTemp === stopDowntimeFlag || that.control.totalTimeTemp === that.control.getTopTime()) {
            $.ajax({
                url: GLOBAL_DOMAIN.pctx + "/register/getPhoneVerificationCode.json",
                data: {
                    challenge: challenge,
                    countryCode: $parent.find('.area_code').text(),
                    phone: that.linkFor.getValue(),
                    type: 1,
                    request_form_verifyCode: lg.Cache.Views[that.control._option.parentName].field['request_form_verifyCode'].getValue()
                },
                dataType: "jsonp",
                jsonp: "jsoncallback",
                cache: false
            }).done(function(result) {
                var stateData = phoneCodeStateList[result.state],
                    count = that.control.getTopTime(),
                    $verifyInputParent;
                var oneSecond = 1000;
                var oneStep = 1;
                if (result.state === senseErrorCode) {
                    ajaxError(result.message);
                    return;
                }
                if (result.state === succCode) {
                    verifySenseChallenge = challenge;
                    $verifyInputParent = $parent.find('[data-propertyname="phoneVerificationCode"]');
                    $verifyInputParent.find('.last_child').addClass('btn_disabled').prop('disabled', true);
                    clearInterval(timer);
                    timer = setInterval(function() {
                        // 语音验证重新激活
                        if (--count < firstIndex) {
                            clearInterval(timer);

                            // 更新短信验证码状态
                            $verifyInputParent.find('.first_child').removeClass('input_warning');
                            $verifyInputParent.find('.last_child').removeClass('btn_disabled').removeProp('disabled');

                            // 显示语音验证码
                            $parent.find('.auto_phone').removeProp('disabled');
                            $parent.find('.verify_tips_count_down').hide();
                            $parent.find('.verify_tips_main').show();
                            that.control.init();
                        // 语音验证已发送
                        } else {
                            if (count === that.control.getTopTime() - oneStep) {
                                $parent.find('.verify_tips_main').hide();
                            }
                            $parent.find('.verify_tips_count_down').html('请留意接收手机来电，' + count + '秒后可重试…').show();
                        }
                    }, oneSecond);
                } else {
                    if (stateData) {
                        that.parent.field[stateData.linkFor].showMessage({message: stateData.message});
                    } else {
                        that.parent.field['phoneVerificationCode'].showMessage({message: result.message});
                    }
                    that.control.init();
                    that.parent.field["request_form_verifyCode"].getVerifyCode();
                }
                that.control.setDisable(false);

            });
        }
    }
    
    // 全角转半角
    $('.HtoC_JS').each(function () {
        $(this).keyup(function() {
            util.HtoC($(this))
        })
    })

    $(".register_enter").keydown(function (event) {
        if(event.keyCode === 13) {
            window.LGWebTj && window.LGWebTj({
                _lt: 'pcclick',
                _address_id: '1m2h',
                added_props: {
                    'action_type': 'enter',
                    'tjEncodeId': '1m2h',
                    'tjNo': '0002'
                }
            });
            if (getAccountType() === "B") {
                submit_func({
                    parent: phoneViewModelB
                });
                return;
            }
            submit_func({
                parent: phoneViewModelC
            });
        }
    })

    $("#register").bind("click", function() {
        if (getAccountType() === "B") {
            submit_func({
                parent: phoneViewModelB
            });
            return;
        }
        submit_func({
            parent: phoneViewModelC
        });
    });

    // B/C身份切换
    $(".register-pop .switch-tab div").bind("click", function () {
        var $this = $(this);
        $(".register-pop .switch-tab div").removeClass("active");
        $this.addClass("active");
        if ($this.hasClass("tab-c")) {
            $(".register-pop .forms-top-wrapper").removeClass("account-b").addClass("account-c");
        } else {
            $(".register-pop .forms-top-wrapper").removeClass("account-c").addClass("account-b");
        }
    })

    // 登录方式切换
    $(".register-pop  .account .change-btn").bind("click", function () {
        $(".register-pop .passport-pop-wrapper.wechat").fadeIn();
        qrCode.openQrCode({
            registerType: getAccountType()
        });
    });
    $(".register-pop .wechat .change-btn").bind("click", function () {
        $(".register-pop .passport-pop-wrapper.wechat").fadeOut();
        qrCode.closeQrCode();
    });

    function ajaxError(err) {
        console.log(err);
    }

    $(".register-pop .login-btn").bind("click", function() {
        $(".register-pop").modal("hide");
        PASSPORT.loginPopup();
    });

    $(".register-pop .close").bind("click", function() {
        qrCode.closeQrCode();
    });

    initSense(function(_sense) {
        sense = _sense;
        isNoLagou = true;
        verifyStyle = "nolagou";
        phoneViewModelB && phoneViewModelB.field["request_form_verifyCode"].setVisible(false);
        phoneViewModelC && phoneViewModelC.field["request_form_verifyCode"].setVisible(false);
    }, function() {
        isNoLagou = false;
        verifyStyle = "lagou";
        phoneViewModelB && phoneViewModelB.field["request_form_verifyCode"].setVisible(true);
        phoneViewModelC && phoneViewModelC.field["request_form_verifyCode"].setVisible(true);
        phoneViewModelB && phoneViewModelB.field["request_form_verifyCode"].getVerifyCode();
        phoneViewModelC && phoneViewModelC.field["request_form_verifyCode"].getVerifyCode();
    });

    module.exports = function () {
        $(".register-pop .passport-pop-wrapper.wechat").hide();
        $(".register-pop .switch-tab .tab-c").trigger("click");
        phoneViewModelB.setClear();
        phoneViewModelC.setClear();
        clearInterval(timer);
        restContryCode();
        $(".verify_tips_main").hide();
        $(".verify_tips_count_down").hide();
        $(".register-pop").modal("show");
        $(".area_code").text("0086");
    }


});
/*!common/components/util/emitter.js*/
;/**
 * @file  Event Emitter
 * @author  Firede[firede@firede.us]
 *
 *
 * 在不同的模块中使用它做事件触发和监听，例如：
 * var Emitter = require( 'emitter' );
 * // 监听
 * global.eventController=new Emitter();
 * global.eventController.on( 'global:editting', function () {
 *     // 监听'global:editting'事件，在这里处理按钮的禁用等操作
 * } );
 * // 触发正在编辑的事件【trigger】，记得传入自己的模块名字
 * global.eventController.emit( 'global:editting', { mod: 'history' } );
 *
 * @type {Emitter}
 */
define('common/components/util/emitter', ['require'], function (require) {

    /**
     * Emitter
     *
     * @exports Emitter
     * @constructor
     */
    function Emitter() {}

    /**
     * Emitter的prototype（为了便于访问）
     *
     * @inner
     */
    var proto = Emitter.prototype;

    /**
     * 获取事件列表
     * 若还没有任何事件则初始化列表
     *
     * @private
     * @return {Object}
     */
    proto._getEvents = function () {
        if (!this._events) {
            this._events = {};
        }

        return this._events;
    };

    /**
     * 获取最大监听器个数
     * 若尚未设置，则初始化最大个数为10
     *
     * @private
     * @return {number}
     */
    proto._getMaxListeners = function () {
        if (isNaN(this.maxListeners)) {
            this.maxListeners = 10;
        }

        return this.maxListeners;
    };

    /**
     * 挂载事件
     *
     * @public
     * @param {string} event 事件名
     * @param {Function} listener 监听器
     * @return {Emitter}
     */
    proto.on = function (event, listener) {
        var events = this._getEvents();
        var maxListeners = this._getMaxListeners();

        events[event] = events[event] || [];

        var currentListeners = events[event].length;
        if (currentListeners >= maxListeners && maxListeners !== 0) {
            throw new RangeError(
                'Warning: possible Emitter memory leak detected. '
                + currentListeners
                + ' listeners added.'
           );
        }

        events[event].push(listener);

        return this;
    };

    /**
     * 挂载只执行一次的事件
     *
     * @public
     * @param {string} event 事件名
     * @param {Function} listener 监听器
     * @return {Emitter}
     */
    proto.once = function (event, listener) {
        var me = this;

        function on() {
            me.off(event, on);
            listener.apply(this, arguments);
        }
        // 挂到on上以方便删除
        on.listener = listener;

        this.on(event, on);

        return this;
    };

    /**
     * 注销事件与监听器
     * 任何参数都`不传`将注销当前实例的所有事件
     * 只传入`event`将注销该事件下挂载的所有监听器
     * 传入`event`与`listener`将只注销该监听器
     *
     * @public
     * @param {string=} event 事件名
     * @param {Function=} listener 监听器
     * @return {Emitter}
     */
    proto.off = function (event, listener) {
        var events = this._getEvents();

        // 移除所有事件
        if (0 === arguments.length) {
            this._events = {};
            return this;
        }

        var listeners = events[event];
        if (!listeners) {
            return this;
        }

        // 移除指定事件下的所有监听器
        if (1 === arguments.length) {
            delete events[event];
            return this;
        }

        // 移除指定监听器（包括对once的处理）
        var cb;
        for (var i = 0; i < listeners.length; i++) {
            cb = listeners[i];
            if (cb === listener || cb.listener === listener) {
                listeners.splice(i, 1);
                break;
            }
        }
        return this;
    };

    /**
     * 触发事件
     *
     * @public
     * @param {string} event 事件名
     * @param {...*} args 传递给监听器的参数，可以有多个
     * @return {Emitter}
     */
    proto.emit = function (event) {
        var events = this._getEvents();
        var listeners = events[event];
        var args = Array.prototype.slice.call(arguments, 1);

        if (listeners) {
            listeners = listeners.slice(0);
            for (var i = 0, len = listeners.length; i < len; i++) {
                listeners[i].apply(this, args);
            }
        }

        return this;
    };

    /**
     * 返回指定事件的监听器列表
     *
     * @public
     * @param {string} event 事件名
     * @return {Array} 监听器列表
     */
    proto.listeners = function (event) {
        var events = this._getEvents();
        return events[event] || [];
    };

    /**
     * 设置监听器的最大个数，为0时不限制
     *
     * @param {number} number 监听器个数
     * @return {Emitter}
     */
    proto.setMaxListeners = function (number) {
        this.maxListeners = number;

        return this;
    };

    /**
     * 将Emitter混入目标对象
     *
     * @param {Object} obj 目标对象
     * @return {Object} 混入Emitter后的对象
     */
    Emitter.mixin = function (obj) {
        for (var key in Emitter.prototype) {
            obj[key] = Emitter.prototype[key];
        }
        return obj;
    };

    return Emitter;

});
/*!common/widgets/passport/dep/md5/md5.js*/
;!function(a){"use strict";function b(a,b){var c=(65535&a)+(65535&b),d=(a>>16)+(b>>16)+(c>>16);return d<<16|65535&c}function c(a,b){return a<<b|a>>>32-b}function d(a,d,e,f,g,h){return b(c(b(b(d,a),b(f,h)),g),e)}function e(a,b,c,e,f,g,h){return d(b&c|~b&e,a,b,f,g,h)}function f(a,b,c,e,f,g,h){return d(b&e|c&~e,a,b,f,g,h)}function g(a,b,c,e,f,g,h){return d(b^c^e,a,b,f,g,h)}function h(a,b,c,e,f,g,h){return d(c^(b|~e),a,b,f,g,h)}function i(a,c){a[c>>5]|=128<<c%32,a[(c+64>>>9<<4)+14]=c;var d,i,j,k,l,m=1732584193,n=-271733879,o=-1732584194,p=271733878;for(d=0;d<a.length;d+=16)i=m,j=n,k=o,l=p,m=e(m,n,o,p,a[d],7,-680876936),p=e(p,m,n,o,a[d+1],12,-389564586),o=e(o,p,m,n,a[d+2],17,606105819),n=e(n,o,p,m,a[d+3],22,-1044525330),m=e(m,n,o,p,a[d+4],7,-176418897),p=e(p,m,n,o,a[d+5],12,1200080426),o=e(o,p,m,n,a[d+6],17,-1473231341),n=e(n,o,p,m,a[d+7],22,-45705983),m=e(m,n,o,p,a[d+8],7,1770035416),p=e(p,m,n,o,a[d+9],12,-1958414417),o=e(o,p,m,n,a[d+10],17,-42063),n=e(n,o,p,m,a[d+11],22,-1990404162),m=e(m,n,o,p,a[d+12],7,1804603682),p=e(p,m,n,o,a[d+13],12,-40341101),o=e(o,p,m,n,a[d+14],17,-1502002290),n=e(n,o,p,m,a[d+15],22,1236535329),m=f(m,n,o,p,a[d+1],5,-165796510),p=f(p,m,n,o,a[d+6],9,-1069501632),o=f(o,p,m,n,a[d+11],14,643717713),n=f(n,o,p,m,a[d],20,-373897302),m=f(m,n,o,p,a[d+5],5,-701558691),p=f(p,m,n,o,a[d+10],9,38016083),o=f(o,p,m,n,a[d+15],14,-660478335),n=f(n,o,p,m,a[d+4],20,-405537848),m=f(m,n,o,p,a[d+9],5,568446438),p=f(p,m,n,o,a[d+14],9,-1019803690),o=f(o,p,m,n,a[d+3],14,-187363961),n=f(n,o,p,m,a[d+8],20,1163531501),m=f(m,n,o,p,a[d+13],5,-1444681467),p=f(p,m,n,o,a[d+2],9,-51403784),o=f(o,p,m,n,a[d+7],14,1735328473),n=f(n,o,p,m,a[d+12],20,-1926607734),m=g(m,n,o,p,a[d+5],4,-378558),p=g(p,m,n,o,a[d+8],11,-2022574463),o=g(o,p,m,n,a[d+11],16,1839030562),n=g(n,o,p,m,a[d+14],23,-35309556),m=g(m,n,o,p,a[d+1],4,-1530992060),p=g(p,m,n,o,a[d+4],11,1272893353),o=g(o,p,m,n,a[d+7],16,-155497632),n=g(n,o,p,m,a[d+10],23,-1094730640),m=g(m,n,o,p,a[d+13],4,681279174),p=g(p,m,n,o,a[d],11,-358537222),o=g(o,p,m,n,a[d+3],16,-722521979),n=g(n,o,p,m,a[d+6],23,76029189),m=g(m,n,o,p,a[d+9],4,-640364487),p=g(p,m,n,o,a[d+12],11,-421815835),o=g(o,p,m,n,a[d+15],16,530742520),n=g(n,o,p,m,a[d+2],23,-995338651),m=h(m,n,o,p,a[d],6,-198630844),p=h(p,m,n,o,a[d+7],10,1126891415),o=h(o,p,m,n,a[d+14],15,-1416354905),n=h(n,o,p,m,a[d+5],21,-57434055),m=h(m,n,o,p,a[d+12],6,1700485571),p=h(p,m,n,o,a[d+3],10,-1894986606),o=h(o,p,m,n,a[d+10],15,-1051523),n=h(n,o,p,m,a[d+1],21,-2054922799),m=h(m,n,o,p,a[d+8],6,1873313359),p=h(p,m,n,o,a[d+15],10,-30611744),o=h(o,p,m,n,a[d+6],15,-1560198380),n=h(n,o,p,m,a[d+13],21,1309151649),m=h(m,n,o,p,a[d+4],6,-145523070),p=h(p,m,n,o,a[d+11],10,-1120210379),o=h(o,p,m,n,a[d+2],15,718787259),n=h(n,o,p,m,a[d+9],21,-343485551),m=b(m,i),n=b(n,j),o=b(o,k),p=b(p,l);return[m,n,o,p]}function j(a){var b,c="";for(b=0;b<32*a.length;b+=8)c+=String.fromCharCode(a[b>>5]>>>b%32&255);return c}function k(a){var b,c=[];for(c[(a.length>>2)-1]=void 0,b=0;b<c.length;b+=1)c[b]=0;for(b=0;b<8*a.length;b+=8)c[b>>5]|=(255&a.charCodeAt(b/8))<<b%32;return c}function l(a){return j(i(k(a),8*a.length))}function m(a,b){var c,d,e=k(a),f=[],g=[];for(f[15]=g[15]=void 0,e.length>16&&(e=i(e,8*a.length)),c=0;16>c;c+=1)f[c]=909522486^e[c],g[c]=1549556828^e[c];return d=i(f.concat(k(b)),512+8*b.length),j(i(g.concat(d),640))}function n(a){var b,c,d="0123456789abcdef",e="";for(c=0;c<a.length;c+=1)b=a.charCodeAt(c),e+=d.charAt(b>>>4&15)+d.charAt(15&b);return e}function o(a){return unescape(encodeURIComponent(a))}function p(a){return l(o(a))}function q(a){return n(p(a))}function r(a,b){return m(o(a),o(b))}function s(a,b){return n(r(a,b))}function t(a,b,c){return b?c?r(b,a):s(b,a):c?p(a):q(a)}"function"==typeof define&&define.amd?define('common/widgets/passport/dep/md5/md5', ['require'], function(require){return t}):a.md5=t}(this);